调用LINQ中的表达式以使用LINQkit选择实体

本文关键字:LINQkit 选择 实体 LINQ 表达式 调用 | 更新日期: 2023-09-27 18:22:46

以下是我想要做的:

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。

调用LINQ中的表达式以使用LINQkit选择实体

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

第二个问题是选择方法接受类型为的对象

Expression<Func<TSource, TResult>>

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

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

因此,必须对传递Item对象作为参数的第二个表达式调用.Invoke(),方法与传递MyClassDbSet对象"o"的方法相同。事实上,这两个select语句只有语法上的不同,它们本质上做着相同的事情。

并且您不应该对表达式调用.Compilet(),这会产生一个:

Func<TSource, TResult>

它是表达式树的已编译版本的委托,无法转换为SQL表达式。更多信息可以在这里找到。

它应该与以下变化一起工作:

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)) 
            }
        );
    }
}

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

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

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