LINQ-to-SQL «Недопустимый доступ к элементу для типа» с объединенным и скомпилированным запросом - PullRequest
2 голосов
/ 08 июля 2010

У меня есть несколько запросов, которые я хотел бы объединить вместе, а затем собрать все. Не скомпилированный запрос выполняется нормально, но «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 };
}

EDIT

Похоже, что объединение и группировка не имеют значения. Удаление этих элементов из запроса по-прежнему вызывает исключение при компиляции:

    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 ]

0 голосов
/ 26 октября 2010

У меня была та же проблема, и мне показалось, что у меня получилось избавиться от встроенного статического вызова метода, который возвратил IQueryable <>, чтобы я сохранил этот отложенный запрос в переменной и сослался на него.

Я думаю, что это ошибка в Linq to SQL, но, по крайней мере, существует разумный обходной путь.

0 голосов
/ 08 июля 2010

Я предполагаю, что компилятор linq не понимает методы, возвращающие IQueryable.

Для компиляции эти методы, вероятно, должны будут возвращать некоторую форму выражения <>.

...