可以访问'this'的非静态表达式<Func <X >>

Hug*_*une 8 c# linq lambda expression-trees linq-to-sql

我有一个数据库表Item,并使用linq-to-sql访问它.

我可以为Items定义一个自定义方法IsSpecial(),如果Item.id的平方根是偶数,则返回true:

partial class Item
{
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0);
}
Run Code Online (Sandbox Code Playgroud)

然后我可以在linq-to-sql查询中使用该属性,如下所示:

 datacontext.Item.Where(Item.IsSpecial)
Run Code Online (Sandbox Code Playgroud)

现在出于审美原因,我想让IsSpecial非静态并修改它,所以我可以像这样调用它:

 datacontext.Item.Where(i => i.IsSpecial())
Run Code Online (Sandbox Code Playgroud)

理想情况下,这也允许组合语句,上述(工作)snytax不允许:

 datacontext.Item.Where(i => i.IsSpecial() && i.Id >100)
Run Code Online (Sandbox Code Playgroud)

定义此方法的正确语法是什么?

这不起作用:

partial class Item
{
    public Expression<Func<bool>> IsSpecial = ( () => Math.Sqrt(this.Id)%2==0 );
    // 'this' keyword not available in current context
}
Run Code Online (Sandbox Code Playgroud)

编辑: 我开始怀疑我要求的语法根本不允许

我想我可以忍受 datacontext.Item.Where(Item.IsSpecial).Where(i => i>100)

小智 4

partial class Item
{
    public static Expression<Func<Item, bool>> IsSpecial = (i => Math.Sqrt(i.Id)%2==0);
}
Run Code Online (Sandbox Code Playgroud)

建议:添加readonly关键字。

然后我可以在 linq-to-sql 查询中使用该属性,如下所示:

datacontext.Item.Where(Item.IsSpecial)
Run Code Online (Sandbox Code Playgroud)

是的,因为Where接受类型为 的参数Expression<Func<Item, bool>>,即Item.IsSpecial

现在出于美观原因,我想让 IsSpecial 成为非静态的并修改它,这样我就可以这样调用它:

datacontext.Item.Where(i => i.IsSpecial())
Run Code Online (Sandbox Code Playgroud)

这不起作用的原因是因为它IsSpecial不是一个函数,而是一个表达式树。()只能应用于函数。表达式树描述了一个函数,但不是一个函数。您可以使用以下命令创建真实函数expression.Compile()

datacontext.Item.Where(i => (IsSpecial.Compile()) (i))
Run Code Online (Sandbox Code Playgroud)

然而,这是行不通的,因为再次Where传递了一个表达式树,但IsSpecial.Compile()实际上并没有被调用。LINQ to SQL 尝试将其转换为 SQL,但由于无法识别而失败Expression.Compile,并引发异常。

但是,如果您可以(IsSpecial.Compile())在 LINQ to SQL 看到它之前进行替换...

这就是LINQKit 的用武之地:

它只提供了一点表达式树操作来使其工作。

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i))
Run Code Online (Sandbox Code Playgroud)

创建.AsExpandable()一个包装器datacontext.Item来预过滤表达式。

理想情况下,这还允许组合语句,而上述(工作)snytax 不允许:

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100)
Run Code Online (Sandbox Code Playgroud)

没问题:

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i) && i.Id > 100)
Run Code Online (Sandbox Code Playgroud)