繁体   English   中英

如何“拆分”或优化Linq to Sql查询。

[英]How to “split up” or optimize a Linq to Sql query.

背景

我们有一个AdvancedSearchModel ,它只是一个带有多个字符串的结构。 SerialNumbers是一串用逗号分隔的序列号(长度为10个字符)。 这被拆分为字符串数组。 我们正在搜索具有一列SerialNumber Devices表。 我们还需要对这些搜索短语进行部分匹配,以解释“ Any和“ Contains用法。 AdvancedSearchModel中大约有10个字符串,我们可以将每个字符串毫无问题地应用于查询。

public static IQueryable<Device> ApplySearchQuery(IQueryable<Device> query, AdvancedSearchModel searchModel)
{
    if (!String.IsNullOrWhiteSpace(searchModel.SerialNumbers))
    {
        string[] serialNumbers = searchModel.SerialNumbers.Split(',');
        query = query.Where(d => serialNumbers.Any(s => d.SerialNumber.Contains(s))); 

     }
     // ... more queries added that are part of the search model
}

问题

让我以实施此操作为开头,我们希望一次最多搜索约10个序列号。 但是 ,我们发现用户最多输入100个序列号。 我们收到一个错误,即查询从此嵌套得太深了。 因此,即使我们仅按序列号进行搜索,当serialNumbers超过43个元素时,它也会引发异常。

我不太确定如何拆分此查询,因为它们分别很简单(尽管我们期望结果很慢)。

也许我们可以有一个大约为25的string[]ArrayList ,并扩展此数组列表,即,如果用户搜索100个序列号,则ArrayList将具有4个字符串数组,但是我不确定这是否真的有用。 ..

有任何想法吗?

我想如果您手动生成OR表达式,则可以让EF生成平面OR语句而不是嵌套的子查询:

string[] serialNumbers = searchModel.SerialNumbers.Split(',');
// GetMethod defined at http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
var stringContainsMethod = Helpers.GetMethod((string s) => s.Contains(default(string)));
var serialNumberProperty = Helpers.GetProperty((Device d) => d.SerialNumber);
var parameter = Expression.Parameter(typeof(Device));

// generate a condition d.SerialNumber.Contains(sn) for each sn
var conditions = serialNumbers.Select(sn => Expression.Call(  
    Expression.MakeMemberAccess(parameter, serialNumberProperty), // d.SerialNumber
    stringContainsMethod, // the method to invoke
    Expression.Constant(sn) // equivalent of a string literal for the serial number
));

// generate a lambda we can pass to Where: 
// d => d.SerialNumber.Contains(sn1) || d.SerialNumber.Contains(sn1) || ..
var predicate = Expression.Lambda<Func<Device, bool>>(
    // merge each condition with ORs
    conditions.Aggregate<Expression>((c1, c2) => Expression.OrElse(c1, c2)),
    parameter
);

// apply the predicate
query = query.Where(predicate);

批处理当然也可以。 但是,对于这么小的参数集,则没有必要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM