LINQ(到实体) - 使用整数过滤项目

时间:2009-11-04 22:01:58

标签: linq linq-to-entities

使用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)
                   )
           )
   );

6 个答案:

答案 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