在运行时修改linq查询

本文关键字:查询 linq 修改 运行时 | 更新日期: 2023-09-27 18:04:34

问题陈述

假设我有一个搜索人名的查询:

var result = (from person in container.people select person)
             .Where(p => p.Name.Contains(some_criterion)

这将被转换为包含以下类似子句的SQL查询:

WHERE NAME LIKE '%some_criterion%'

这会对性能产生一些影响,因为数据库无法有效地使用名称列上的索引(如果我没有弄错的话,请使用index scan v.s.index seek(。

为了解决这个问题,我可以决定只启动With((,使用类似子句生成查询,如:

WHERE NAME LIKE 'some_criterion%'

这使SQL server能够使用索引查找并以牺牲某些功能为代价提供性能。

我希望能够为用户提供一个选择:将行为默认为使用StartsWith,但如果用户希望使用Contains((搜索"增加灵活性",则应使用该选项。

我试过什么

我认为这很琐碎,于是继续在字符串上实现了一个扩展方法。但是,LINQ当然不接受这一点,并且抛出了一个异常。

现在,我当然可以继续使用if或switch语句,并为每种情况创建一个查询,但我更愿意"在更高的级别上"或更通用地解决这个问题。简而言之:由于实际应用程序的复杂性,使用if语句来区分用例是不可行的。这会导致大量的重复和混乱。我真的希望能够以某种方式封装不同的行为(Contains、StartsWith、EndsWith(。

问题

我应该去哪里找或者找什么?这是IQueryables的可堆肥性的情况吗?我很困惑!

在运行时修改linq查询

与其使事情过于复杂,不如只使用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;

我相信这符合你对的要求

我真的希望能够封装不同的行为(包含、起始于、结束于(。

您可以在枚举查询之前动态更改查询。

var query = container.people.AsQueryable();
if (contains)
{
    query = query.Where(p => p.Name.Contains(filter));
}
else
{
    query = query.Where(p => p.Name.StartsWith(filter));
}

尝试dis:

var result = (from person in container.people select person)
                .Where(p => some_bool_variable ? p.Name.Contains(some_criterium) : p.Name.StartsWith(some_criterium));

现实生活中的查询非常庞大,并且与其他几个查询不一致。这和我的问题一样,不是我正在寻找的解决方案

Sinse您的查询是巨大的:难道您不能只定义处理所有内容的存储过程,并使用特定的查询参数来调用它吗?