如何为EntitySet构造Where子句

本文关键字:Where 子句 构造 EntitySet | 更新日期: 2023-09-27 18:03:43

假设我有两个用外键约束连接的表。考虑下面的代码:

using(var dc = TestDataContext())
{
    IQueryable<ParentTable> query = dc.ParentTable;  
    query = query.Where(t => t.ChildTable.Where(c => c.Name.StartsWith("#")).Any());
    Console.WriteLine(query.Count());
}

如果我需要在某些条件下扩展Where子句,我将简单地链接Where子句:

if(...)
    query = query.Where(...);
...

实际上是通过sql中的AND语句添加到原来的Where子句。

现在想象一下,我需要在ParentTable Where子句中动态地在ChildTable上构造Where子句…

I tried do this:

using(var dc = TestDataContext())
{
    IQueryable<ParentTable> query = dc.ParentTable;  
    //here specify the necessary condition 
    Func<ChildTable, bool> where;
    if(...)
        where = c => c.Name.StartsWith("#");
    else ...
    query = query.Where(t => t.ChildTable.Any(where));
    Console.WriteLine(query.Count());
}

然而,它抛出NotSupportedException,说它不能正确地将where Func指定为Any转换为sql。

我想我可以指定Expression<Func<ChildTable, bool>>,但t.ChildTableEntitySet<ChildTable>,所以它不实现IQueryable<T>…因此,自定义的Func<>不能正确地转换为sql。

除了每次重写整个语句之外,还有什么方法可以达到这个目的吗?

1. query = query.Where(t => t.ChildTable.Where(c => c.Name.StartsWith("#")).Any());
2. query = query.Where(t => t.ChildTable.Where(c => c.Name.StartsWith("#") && ...).Any()));

如何为EntitySet构造Where子句

在需要动态where子句的情况下,我喜欢使用PredicateBuilder。

将该站点上的示例翻译为您的问题将得到以下代码。如果您使用EF,您可能需要使用.AsExpandable(),请参阅链接以获取更多信息。

var predicate = PredicateBuilder.False<ParentTable>();
predicate = predicate.Or(p => p.ChildTable.Any(c => c.Name.StartsWith("#"));
var keywords = "search terms go here";
foreach (var keyword in keywords)
{
  var temp = keyword;
  predicate = predicate.Or(p => p.ChildTable.Any(c => c.Name.Contains(temp));
}
using(var dc = TestDataContext())
{
  Console.WriteLine(dc.ParentTable.Where(predicate).Count());
}