如何为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.ChildTable
是EntitySet<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()));
…
在需要动态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());
}