我正在尝试使用LINQ-to-SQL实现以下算法:
给定字符串L的列表,返回DB中的每一行R,其中L中的每个字符串都是R中其中一个列值的子字符串。
问题是我如何迭代地为L中的每个字符串执行此操作?我不知道如何将它全部整合到一个Linq-To-SQL语句中。请注意,我在编写代码时没有问题:
field1.contains(...) || field2.contains(...) || ...
因为没有那么多列。
例如,如果输入是
[“查理”,“医生”,“Kor”]
我们将输出所有带有“Charlie”字段作为子字符串的行,带有“Doctor”作为子字符串的字段,以及带有“Kor”作为子字符串的字段。
我想到的一种方法是为每个输入值进行单独的SQL查询,并采用所有这些的交集。
另一种方法是从输入中选择一个字符串,对其进行SQL查询,将其转换为列表,并使用C#中的LINQ一次过滤掉其余字符串。
有关最佳方法的任何想法吗?
答案 0 :(得分:2)
我会尝试All扩展方法(EF6支持它,不确定LINQ to SQL):
List<string> values = new List<string> { "Charlie", "Doctor", "Kor" };
var query = db.Table
.Where(r => values.All(v => r.Field1.Contains(v) || r.Field2.Contains(v) || ...));
更新:嗯,假设是错误的 - 正如评论中提到的,不幸的是LINQ to SQL不支持上面的构造(对它们感到羞耻)。
在这种情况下,我会动态构建一个相应的谓词表达式。
在这种特殊情况下,我们需要这样的内容(适用于N
字段和M
值):
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, ...);
应该导致单个SQL查询哪个IMO应该是最佳的,因为繁重的工作将由数据库引擎完成。当然,查询很可能会导致全表扫描,但即使使用单Contains
(SQL LIKE
)条件也会发生同样的情况。
答案 1 :(得分:-1)
试试这个(我使用Lists做了一个例子):
var dbValues = new List<string> {"hello", "how", "are", "you"};
var substrings = new List<string> {"ello", "re"};
var result = dbValues.Where(i => substrings.Any(l => i.Contains(l))).ToList();
结果将包含{“ hello ”,“ ”}
数据库示例:
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();
}