假设我有两个表连接外键约束。请考虑以下代码:
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中的Where
语句添加到原始AND
子句中。
现在想象一下,我需要在Where
ChildTable
子句中的ParentTable
上动态构建Where
子句...
我试着这样做:
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()));
...
答案 0 :(得分:0)
如果我需要动态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());
}