【问题标题】:Call Expression within a LINQ to Entities Select with LINQkit使用 LINQkit 在 LINQ to Entities Select 中调用表达式
【发布时间】:2013-07-16 18:33:55
【问题描述】:

这是我想做的:

class MyDbContext : DbContext 
{
    private static Expression<Func<MyClass, int>> myExpression1 = x => /* something complicated ... */;
    private static Expression<Func<Item, int>> myExpression2 = x => /* something else complicated ... */;

    public object GetAllData()
    {
        return (
            from o in MyClassDbSet.AsExpandable() 
            select new 
            {
                data1 = myExpression1.Invoke(o),                      // problem 1
                data2 = o.Items.Select(myExpression2.Compile())       // problem 2
            }
        );
    }
}

更新:

myExpression 必须与我的查询分开,因为我想在多个 LINQ 查询中重用它。

更新 2:

myExpression 分隔为myExpression1myExpression2,以明确我想分别重用它们。

更新 3:

将 LINQkit 添加到示例中。

问题 1 抛出:无法将“System.Linq.Expressions.FieldExpression”类型的对象转换为“System.Linq.Expressions.LambdaExpression”类型。

问题 2 抛出:内部 .NET Framework 数据提供程序错误 1025。

【问题讨论】:

  • 看看LINQKit
  • 谢谢,我试试!
  • @svick,我更新了问题以反映我现在使用 LINQkit 时遇到的问题...

标签: c# linq-to-entities linq-expressions linqkit


【解决方案1】:

关于使用 LinqKit 时的第一个问题,您需要在 .Invoke() 之前将表达式分配给局部变量。更完整的解释可以在this question找到。

第二个问题是select方法接受一个类型的对象:

Expression<Func<TSource, TResult>>

这意味着您必须提供一个接受 TSource 对象作为参数并返回 TResult 对象的 lambda 表达式。

您的 TSource 对象是 Item,即您从中进行查询的表。您的 TResult 在您的示例中是一个 int,这就是您在表达式中定义的内容。

因此,您必须在传递 Item 对象作为参数的第二个表达式上调用 .Invoke(),方法与传递 MyClassDbSet 对象“o”的方式相同。实际上,两个 select 语句只有句法上的区别,它们本质上是做同样的事情。

而且你不应该在表达式上调用 .Compile(),这会产生:

Func<TSource, TResult>

这是表达式树的编译版本的委托,不能转换为 SQL 表达式。更多信息可以找到here

它应该适用于以下更改:

class MyDbContext : DbContext 
{
    private static Expression<Func<MyClass, int>> myExpression1 = x => /* something complicated ... */;
    private static Expression<Func<Item, int>> myExpression2 = x => /* something else complicated ... */;

    public object GetAllData()
    {
        Expression<Func<MyClass, int>> myLocalExpression1 = myExpression1;
        Expression<Func<MyClass, int>> myLocalExpression2 = myExpression2;

        return (
            from o in MyClassDbSet.AsExpandable() 
            select new 
            {
                data1 = myLocalExpression1.Invoke(o),
                data2 = o.Items.Select(item => myLocalExpression1.Invoke(item)) 
            }
        );
    }
}

【讨论】:

    【解决方案2】:

    您可以尝试只使用委托而不是表达式:

      private static Func<MyClass, int> myExpression = x => /* something complicated ... */;
    

    这种方法的问题在于,将从数据库中检索整个 MyClass,而不仅仅是计算表达式所需的字段。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-20
      • 1970-01-01
      • 1970-01-01
      • 2016-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多