LINQ-to-SQL "Недопустимый доступ к элементу для типа" с объединенным и скомпилированным запросом
У меня есть несколько запросов, которые я хотел бы объединить вместе, а затем собрать все. Нескомпилированный запрос выполняется нормально, но "InvalidOperationException: доступ к элементу 'Int32 Id' для UserQuery+Foo недопустим для типа" System.Linq.IQueryable`1[UserQuery+Foo] ". исключение выдается, когда один и тот же запрос компилируется и выполняется.
Как это исправить?
void Main()
{
var db = new MyDataContext( "..." );
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from ab in GetA(dc).Union( GetB(dc) )
group ab by new { ab.Id, ab.Name } into grp
select new Foo
{
Id = grp.Key.Id,
Name = grp.Key.Name,
Total = grp.Count()
};
var final = CompiledQuery.Compile ( queryExpression );
var result1 = queryExpression.Compile () (db, 0); // calling the original query works fine
var result2 = final (db, 0); // calling the compiled query throws an exception
}
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public int Total { get; set; }
}
IQueryable<Foo> GetA( DataContext db )
{
return from b in db.GetTable<Bar>()
where b.IsActive
select new Foo { Id = b.Id, Name = b.Name };
}
IQueryable<Foo> GetB( DataContext db )
{
return from b in db.GetTable<Bar>()
where !b.IsActive
select new Foo { Id = b.Id, Name = b.Name };
}
РЕДАКТИРОВАТЬ
Похоже, объединение и группировка не имеют значения. Удаление этих элементов из запроса все еще вызывает исключение при компиляции:
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from a in GetA(dc)
select new Foo
{
Id = a.Id,
Name = a.Name,
Total = 42
};
Замена звонка на GetA(dc)
с dc.GetTable<Bar>()
и добавление предложения where решает проблему.
Таким образом, объединение отдельных запросов вместе, как это просто невозможно для скомпилированных запросов?
РЕДАКТИРОВАТЬ № 2
Ответ Джеймса ударил гвоздь по голове. Упрощение запроса еще больше выявляет корень проблемы:
Expression < Func < DataContext, int, IQueryable < Foo > > > queryExpression = (DataContext dc, int unused) =>
from a in GetA(dc)
select a;
Этот запрос выбрасывает NotSupportedException: Method 'System.Linq.IQueryable``1[UserQuery+Foo] GetA(System.Data.Linq.DataContext)' has no supported translation to SQL.
Вытягивание вызова GetA в отдельное назначение переменной, затем использование этой переменной в запросе InvalidOperationException: Sequence contains more than one element
исключение.
2 ответа
У меня была та же проблема, и мне показалось, что у меня получилось отделить встроенный статический вызов метода, который возвратил IQueryable<>, чтобы я сохранил этот отложенный запрос в переменной и сослался на него.
Я думаю, что это ошибка в Linq to SQL, но, по крайней мере, есть разумное решение.
Я предполагаю, что компилятор linq не понимает методы, возвращающие IQueryable.
Чтобы скомпилировать его, эти методы, вероятно, должны будут возвращать некоторую форму Expression<>.