【问题标题】:LINQ-to-SQL "Member access not legal on type" exception with unioned and compiled queryLINQ-to-SQL“成员访问在类型上不合法”异常与联合和编译查询
【发布时间】:2010-07-08 15:23:19
【问题描述】:

我想将多个查询合并在一起,然后编译整个内容。未编译的查询运行良好,但“InvalidOperationException:'UserQuery+Foo'的成员访问'Int32 Id'在'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&lt;Bar&gt;() 并添加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 异常。

【问题讨论】:

    标签: linq-to-sql union compiled-query linq.compiledquery


    【解决方案1】:

    我有同样的问题,似乎对我有用的是分离出一个返回 IQueryable 的内联静态方法调用,以便我将这个延迟查询存储到一个变量中并引用它。

    我认为这是 Linq to SQL 中的一个错误,但至少有一个合理的解决方法。

    【讨论】:

      【解决方案2】:

      我的猜测是 linq 编译器不理解返回 IQueryable 的方法。

      要编译它,这些方法可能必须返回某种形式的表达式。

      【讨论】:

      • 我有点明白你的意思,但是 from 子句的文档说 "from 子句中引用的数据源必须具有 IEnumerable 类型,IEnumerable)>) 或派生类型,例如 IQueryable)>)。” 我想这意味着我需要从表达式而不是内置的语言,但我不确定如何开始使用它。
      猜你喜欢
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-10
      • 2015-06-27
      • 1970-01-01
      相关资源
      最近更新 更多