8

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

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

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

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

 datacontext.Item.Where(Item.IsSpecial)

现在出于美学原因,我想将 IsSpecial 设为非静态并对其进行修改,以便我可以这样称呼它:

 datacontext.Item.Where(i => i.IsSpecial())

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

 datacontext.Item.Where(i => i.IsSpecial() && i.Id >100)

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

这不起作用:

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

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

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

4

3 回答 3

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

建议:添加readonly关键字。

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

datacontext.Item.Where(Item.IsSpecial)

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

现在出于美学原因,我想将 IsSpecial 设为非静态并对其进行修改,以便我可以这样称呼它:

datacontext.Item.Where(i => i.IsSpecial())

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

datacontext.Item.Where(i => (IsSpecial.Compile()) (i))

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

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

这就是LINQKit的用武之地:

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

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i))

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

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

datacontext.Item.Where(i => i.IsSpecial() && i.Id >100)

没问题:

datacontext.Item.AsExpandable().Where(i => (IsSpecial.Compile()) (i) && i.Id > 100)
于 2012-04-12T18:26:36.143 回答
2

您可以直接使用 IsSpecial:

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

datacontext.Item.Where(Item.IsSpecial)
于 2012-04-12T16:36:53.743 回答
1

尝试将 IsSpecial 的赋值放在构造函数中,并让所有其他构造函数委托给它,或者您可以使用 OnCreated 等分部方法将表达式分配给 IsSpecial。代替partial class Item

partial void OnCreated()
{
     IsSpecial = () => Math.Sqrt(this.Id)%2==0;
}

这样做将始终分配 IsSpecial,并允许访问“this”。

于 2012-04-12T17:21:51.837 回答