c# – 在运行时修改linq查询
作者:互联网
问题陈述
假设我有一个搜索人名的查询:
var result = (from person in container.people select person)
.Where(p => p.Name.Contains(some_criterion)
这将被转换为包含以下like子句的SQL查询:
WHERE NAME LIKE '%some_criterion%'
这有一些性能影响,因为数据库无法有效地使用名称列上的索引(索引扫描v.s.索引搜索,如果我没有记错).
为了解决这个问题,我可以决定只使用StartsWith(),使用like子句生成查询,如:
WHERE NAME LIKE 'some_criterion%'
这使SQL服务器能够以某些功能为代价使用索引查找和交付性能.
我希望能够为用户提供一个选择:默认行为使用StartsWith,但是如果用户希望使用Contains()进行搜索的“增加的灵活性”,那么应该使用.
我试过了什么
我认为这是微不足道的,并继续在字符串上实现了一个扩展方法.但是当然,LINQ不接受这个并抛出异常.
现在,我当然可以使用if或switch语句并为每个案例创建一个查询,但我更倾向于在“更高级别”或更一般地解决这个问题.
简而言之:由于现实应用程序的复杂性,使用if语句来区分用例是不可行的.这会导致很多重复和混乱.我真的希望能够以某种方式封装变化的行为(Contains,StartsWith,EndsWith).
题
我应该在哪里看,或者我应该寻找什么?这是与IQueryables的可组合性的案例吗?我很困惑!
解决方法:
使用if语句怎么样,而不是过度复杂化?
var query = from person in container.people
select person;
if (userWantsStartsWith)
{
query = from p in query
where p.Name.Contains(some_criterion)
select p;
}
else
{
query = from p in query
where p.Name.StartsWith(some_criterion)
select p;
}
更新
如果你真的需要更复杂的东西,可以试试看LinqKit.它可以让你做到以下几点.
var stringFunction = Lambda.Expression((string s1, string s2) => s1.Contains(s2));
if (userWantsStartsWith)
{
stringFunction = Lambda.Expression((string s1, string s2) => s1.StartsWith(s2));
}
var query = from p in container.people.AsExpandable()
where stringFunction.Invoke(p.Name, some_criterion)
select p;
我相信这符合你的要求
I’d really like to be able to encapsulate the varying behavior
(Contains, StartsWith, EndsWith) somehow.
标签:c,linq,entity-framework,extension-methods 来源: https://codeday.me/bug/20190718/1493518.html