Linq to SQL怎么做“where [column] in(values of values)”

时间:2009-07-02 16:59:58

标签: linq linq-to-sql

我有一个函数,我得到一个id列表,我需要返回一个匹配与id相关的描述的列表。 E.g:

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

因此,如果我自己创建sql,我会简单地执行以下操作(其中in子句包含codeIds参数中的所有值):

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

在Linq to Sql中我似乎无法找到相当于“IN”的子句。到目前为止我发现的最好(不起作用)是:

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

问题是,我无法动态生成linq到sql的“OR”子句列表,因为它们是在编译时设置的。

如何使用Linq to Sql完成检查列的where子句在动态值列表中?

6 个答案:

答案 0 :(得分:149)

使用

where list.Contains(item.Property)

或者在你的情况下:

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

但你可以用点符号来做那个:

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

答案 1 :(得分:24)

你也可以使用:

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

答案 2 :(得分:1)

我一直在Jon Skeet的回答中使用这个方法,但是我使用Concat发现了另一个。 Concat方法在有限的测试中表现略好,但这很麻烦,我可能会坚持使用Contains,或者我会写一个帮助方法来为我做这个。无论哪种方式,如果有人有兴趣,这是另一种选择:

方法

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

性能测试

这不是远程科学的。我想你的数据库结构和列表中涉及的ID数量会产生重大影响。

我设置了一个测试,其中我对ConcatContains各进行了100次试验,其中每次试验都涉及选择由随机主键列表指定的25行。我已经运行了大约十几次,并且大多数情况下Concat方法的速度提高了5-10%,尽管有一次Contains方法仅通过smidgen获胜。

答案 3 :(得分:0)

 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

答案 4 :(得分:0)

没有实体框架 Net Core 2

string[] names = stringsTest.name.Split('|');

if (names.Length > 1)
{
    query = query.Where(w => names.Contains(w.name));
}
else
{
    query = query.Where(w => w.name== stringsTest.name);
}

var listEntity = await query.ToListDtoAsync(stringsTest);

答案 5 :(得分:-1)

这是我使用HashSet的方法

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

HashSet基本上接近O(1),因此您的复杂度仍然为O(n)。