动态where子句(OR)在LINQ到实体 [英] Dynamic where clause (OR) in Linq to Entities
问题描述
在 我学会了如何构建一个动态查询使用LINQ的延迟执行。但查询实际使用和 WHERE条件的串联。
我怎样才能达到同样的查询,但逻辑或?
由于标志枚举,查询应搜索的用户名的 WindowsUsername 的或的两个的:
大众用户的getUser(IdentifierType型,字符串标识符)
{
使用(VAR上下文= contextFactory.Invoke())
{
VAR查询从U =在context.Users选择U; 如果(type.HasFlag(IdentifierType.Username))
查询= query.Where(U => u.Username ==标识符); 如果(type.HasFlag(IdentifierType.Windows))
查询= query.Where(U => u.WindowsUsername ==标识符); 返回query.FirstOrDefault();
}
}
通过 LINQKit的 predicateBuilder你可以建立predicates动态的。
VAR的查询=从u在context.Users选择U;
VAR preD = predicate.False<使用者>();如果(type.HasFlag(IdentifierType.Username))
preD = pred.Or(U => u.Username ==标识符);如果(type.HasFlag(IdentifierType.Windows))
preD = pred.Or((U => u.WindowsUsername ==标识符);返回query.Where(pred.Expand())FirstOrDefault();
//或返回query.AsExpandable()式(preD).FirstOrDefault()。
这是什么展开
是:
实体框架的查询处理管道无法处理调用前pressions,这就是为什么你需要调用AsExpandable查询的第一个对象。通过调用AsExpandable,激活LINQKit的前pression访问者类调用替换前pressions用更简单的构造,实体框架可以理解。
块引用>或者:没有它的前pression是
调用
D,从而导致异常的EF
在LINQ前pression节点类型调用不LINQ支持实体。
块引用>后来另外:
还有一个另外的predicate建设者,做相同的,但没有展开:<一href=\"http://petemontgomery.word$p$pss.com/2011/02/10/a-universal-$p$pdicatebuilder/\">http://petemontgomery.word$p$pss.com/2011/02/10/a-universal-$p$pdicatebuilder/
In the post here I learned how to build a dynamic query using the deferred execution of Linq. But the query is actually using an AND concatenation of the WHERE condition.
How can I achieve the same query but with an OR logic?
Due to the Flags enum, the query should search for Username, WindowsUsername or both:
public User GetUser(IdentifierType type, string identifier) { using (var context = contextFactory.Invoke()) { var query = from u in context.Users select u; if (type.HasFlag(IdentifierType.Username)) query = query.Where(u => u.Username == identifier); if (type.HasFlag(IdentifierType.Windows)) query = query.Where(u => u.WindowsUsername == identifier); return query.FirstOrDefault(); } }
解决方案With LINQKit's PredicateBuilder you can build predicates dynamically.
var query = from u in context.Users select u; var pred = Predicate.False<User>(); if (type.HasFlag(IdentifierType.Username)) pred = pred.Or(u => u.Username == identifier); if (type.HasFlag(IdentifierType.Windows)) pred = pred.Or((u => u.WindowsUsername == identifier); return query.Where(pred.Expand()).FirstOrDefault(); // or return query.AsExpandable().Where(pred).FirstOrDefault();
This is what the
Expand
is for:Entity Framework's query processing pipeline cannot handle invocation expressions, which is why you need to call AsExpandable on the first object in the query. By calling AsExpandable, you activate LINQKit's expression visitor class which substitutes invocation expressions with simpler constructs that Entity Framework can understand.
Or: without it an expression is
Invoke
d, which causes an exception in EF:The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Later addition:
There is an alternative predicate builder that does the same but without Expand: http://petemontgomery.wordpress.com/2011/02/10/a-universal-predicatebuilder/
这篇关于动态where子句(OR)在LINQ到实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!