C# 高效地进行迭代LINQ到SQL查询

C# 高效地进行迭代LINQ到SQL查询,c#,sql,linq,linq-to-sql,C#,Sql,Linq,Linq To Sql,我正在尝试使用LINQ to SQL实现以下算法: 给定字符串L的列表,返回数据库中的每一行R,其中L中的每一个字符串都是R中某个列值的子字符串 问题是如何对L中的每个字符串进行迭代?我不知道如何才能巧妙地将其全部放在一个LINQtoSQL语句中。请注意,我在编写以下代码时没有问题: field1.包含(…)| |字段2.包含(…)| |… 因为没有那么多列 例如,如果输入是 [“查理”、“医生”、“科尔”] 我们将输出所有行,其中字段的子字符串为“Charlie”,字段的子字符串为“Docto

我正在尝试使用LINQ to SQL实现以下算法:

给定字符串L的列表,返回数据库中的每一行R,其中L中的每一个字符串都是R中某个列值的子字符串

问题是如何对L中的每个字符串进行迭代?我不知道如何才能巧妙地将其全部放在一个LINQtoSQL语句中。请注意,我在编写以下代码时没有问题:

field1.包含(…)| |字段2.包含(…)| |…

因为没有那么多列

例如,如果输入是

[“查理”、“医生”、“科尔”]

我们将输出所有行,其中字段的子字符串为“Charlie”,字段的子字符串为“Doctor”,字段的子字符串为“Kor”

我想到的一种方法是对每个输入值进行单独的SQL查询,并取所有这些值的交集

另一种方法是从输入中只选取一个字符串,对其进行SQL查询,将其转换为列表,然后使用C#中的LINQ一次过滤掉其余的字符串

有没有什么好办法可以做到这一点?

试试这个(我用列表做了一个例子):

var dbValues=新列表{“你好”、“你好”、“你在吗”、“你”};
var substring=新列表{“ello”,“re”};
var result=dbValues.Where(i=>substring.Any(l=>i.Contains(l)).ToList();
结果将包含{“你好”,“”}

数据库示例:

using (var db = new MyDatabase())
{
    var substrings = new List<string> { "ello", "re" };
    var result = db.MyTable.Where(i => substrings.Any(l => i.Value.Contains(l))).ToList();
}
使用(var db=new MyDatabase())
{
var substring=新列表{“ello”,“re”};
var result=db.MyTable.Where(i=>substring.Any(l=>i.Value.Contains(l)).ToList();
}
我会尝试扩展方法(EF6支持它,但不确定LINQ到SQL):

下面是一个自定义扩展方法,它可以:

public static class QueryableExtensions
{
    public static IQueryable<T> WhereContainsAll<T>(
        this IQueryable<T> source, 
        IEnumerable<string> values,
        params Expression<Func<T, string>>[] members)
    {
        var parameter = Expression.Parameter(typeof(T), "r");
        var body = values
            .Select(value => members
                .Select(member => (Expression)Expression.Call(
                    Expression.MakeMemberAccess(parameter, ((MemberExpression)member.Body).Member),
                    "Contains", Type.EmptyTypes, Expression.Constant(value)))
                .Aggregate(Expression.OrElse))
            .Aggregate(Expression.AndAlso);
        var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
        return source.Where(predicate);
    }
}
公共静态类QueryableExtensions
{
公共静态IQueryable,其中包含所有(
这是可靠的消息来源,
IEnumerable value,
参数表达式[]成员)
{
var参数=表达式参数(类型为(T),“r”);
变量体=值
.选择(值=>成员)
.Select(member=>(Expression)Expression.Call(
Expression.MakeMemberAccess(参数,((MemberExpression)member.Body.member),
“包含”、Type.EmptyTypes、Expression.Constant(值)))
.合计(表示为OrElse))
.骨料(表示为AndAlso);
var谓词=Expression.Lambda(主体,参数);
返回source.Where(谓词);
}
}
示例用法如下所示:

List<string> values = new List<string> { "Charlie", "Doctor", "Kor" };
var query = db.Table.WhereContainsAll(values,
    r => r.Field1, r => r.Field2, r => r.Field3, ...);
List values=新列表{“Charlie”、“Doctor”、“Kor”};
var query=db.Table.WhereContainsAll(值,
r=>r.Field1,r=>r.Field2,r=>r.Field3,…);

这将导致一个单一的SQL查询,IMO应该是最佳的,因为繁重的工作将由数据库引擎完成。当然,查询很可能会导致全表扫描,但即使使用单个
包含
(SQL
LIKE
)条件,也会发生同样的情况。

为什么不进行一次查询,将内容放在何处。其中(r=>r.MyField.Contains(“医生”)| | r.MyField.Contains(“查理”)| |……)我想他要说的是,他不想手动检查每一列。他正在寻找一种检查所有列的方法。不过,你对个人的建议是正确的。这个问题不是手动检查每一列,我很乐意这样做,因为有O(1)列。但是,如果我的输入是数组,我该怎么做呢?从句法上看是什么样的?请把你最后的评论纳入问题中,因为现在还不清楚你在问什么。我已经更新了这个问题。好主意,但不幸的是,我得到了一个NotSupportedException:在查询运算符的LINQ到SQL实现中不能使用本地序列,除了Contains运算符。Argh,太糟糕了:(但要确认的是,这就是你要找的,只需要找到一种方法让它工作就行了?是的。目标是最大限度地提高效率,我的假设是,我给SQL和C#post-processing做的工作越多越好。动态生成复杂表达式的一个很好的例子——查询提供程序不会知道如何翻译问题不是查询内存中的列表,而是查询数据库。好的,如果有人在将该逻辑转换为SQL时遇到问题,那么问题是:使用(var db=new db()){var substring=new list{“ello”,“re”};var result=db.MyTable.Where(i=>substring.Any(l=>i.Value.Contains(l))).ToList();}这不是SQL…这只是一个LINQ查询,在运行时会出错,因为查询提供程序无法将其转换为SQL,如我在第一条评论中所述。我知道这不是生成的SQL,但当您运行它时,您可以使用探查器捕获生成的SQL。不,当您运行它时,您会看到程序崩溃,因为查询提供程序无法将其转换为SQL,就像我已经告诉过你两次的那样。
r => (r.Field1.Contains(value1) || r.Field2.Contains(value1) ... || r.FieldN.Contains(value1))
  && (r.Field1.Contains(value2) || r.Field2.Contains(value2) ... || r.FieldN.Contains(value2))
  ...
  && (r.Field1.Contains(valueM) || r.Field2.Contains(valueM) ... || r.FieldN.Contains(valueM));
public static class QueryableExtensions
{
    public static IQueryable<T> WhereContainsAll<T>(
        this IQueryable<T> source, 
        IEnumerable<string> values,
        params Expression<Func<T, string>>[] members)
    {
        var parameter = Expression.Parameter(typeof(T), "r");
        var body = values
            .Select(value => members
                .Select(member => (Expression)Expression.Call(
                    Expression.MakeMemberAccess(parameter, ((MemberExpression)member.Body).Member),
                    "Contains", Type.EmptyTypes, Expression.Constant(value)))
                .Aggregate(Expression.OrElse))
            .Aggregate(Expression.AndAlso);
        var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
        return source.Where(predicate);
    }
}
List<string> values = new List<string> { "Charlie", "Doctor", "Kor" };
var query = db.Table.WhereContainsAll(values,
    r => r.Field1, r => r.Field2, r => r.Field3, ...);