使用LINQ to Entities,如何确定以逗号分隔的整数字符串中的int列表中的任何项目是否存在?
例如,我想写下面的内容(逻辑上):
collection.Where(collection.DelimitedStringOfInts.Contains(listOfInts.AnyOfThem))
另外,我应该提一下,我正在使用LINQ方法链接,将分隔字符串作为实体的一部分 -
var listOfInts = GetListOfInts();
var query = from x in Db.Items select x;
if (listOfInts != null && listOfInts.Count() > 0)
{
query = query.Where(x => x.DelimitedStringOfInts.Contains(listOfInts.AnyOfThem));
}
更新:
使用Alex的参考文章,我实现了一个工作解决方案如下:
var query = from x in Db.Items select x;
var listOfInts = GetListOfInts();
if (listOfInts != null && listOfInts.Any())
{
//"ToListOfStrings" is a simple extension method I wrote to create a List<string> from a List<int>
var delimitedIds = listOfInts.ToListOfStrings(',');
query = query.Where(
BuildOrExpression<DatabaseItem, string>(x => x.DelimitedStringOfInts, delimitedIds)
);
}
本文中引用的“BuildOrExpression”需要更新。必须将“等于”运算符更改为“包含”运算符。
var contains = values.Select(value =>
(Expression)Expression.Call(
valueSelector.Body,
typeof(string).GetMethod("Contains"),
Expression.Constant(
value,
typeof(TValue)
)
)
);
答案 0 :(得分:5)
看看这个tip,这不是你要求的,但我认为你可以调整它以获得你想要的东西。
亚历
答案 1 :(得分:4)
DelimitedStringOfInts.Split(new char[]{','})
.Select<string, int>(s => int.Parse(s))
.Intersect(listOfInts).Count<int>() > 0
答案 2 :(得分:2)
将字符串转换为HashSet,以获得.Contains的最佳性能。 .Any()应该在找到第一个匹配时返回true。
var stringofInts = "2,3,5,9";
List<int> listOfInts = GetSomeListOfInts();
var set = new HashSet<int>(stringofInts.Split(',').Select(x => int.Parse(x)));
listOfInts.Any(x => set.Contains(x))
答案 3 :(得分:1)
如您所知,该查询无法转换为SQL,因此EF将拒绝翻译查询。
您需要在代码和数据库之间拆分查询,方法是获取分隔的字符串,然后在客户端中检查它们:
query = query.Select(x => x.DelimitedStringOfInts)
.ToList() // Run the query in the database now
.Where(ints => ints.Select(s => int.Parse(s)).Any(listOfInts.Contains));
如果您希望在数据库中运行所有内容,我认为您必须使用sprocs或原始SQL,或者动态构建查询表达式,如Alex James' answer中建议的那样。
您还可以使用Jimmy的答案中的HashSet idea来加速客户端部分。
而且,作为另一个想法(不知道你是否可以这样做)但是如果有可能扩展EF的QueryProvider
,那么就可以将对List.Contains
的调用转换为SQL WHERE ... IN ...
。可能并不容易。顺便说一句,EF 4将具有内置功能。</ p>
答案 4 :(得分:0)
试试这个:
int i = 0;
bool exists = StringOfInts.Split(',').Any(
s => Int32.TryParse(s, out i) &&
listOfInts.Any(n => n == i)
);
答案 5 :(得分:0)
这样可以解决问题......
List<int> integerList = new List<int>() { 1, 2, 3, 4 };
string integersAsString = "1,3,5";
var result = integersAsString.Split(',')
.Select(s => Int32.Parse(s))
.Where(i => integerList.Contains(i));
foreach (var i in result)
Console.WriteLine(i); // prints 1 and 3