Linq to SQL怎么做“where in(值列表)”

我有一个函数,我得到一个ID列表,我需要返回一个列表匹配与该ID相关联的描述。 例如:

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 } 

所以,如果我自己创build了这个sql,我只需要做如下的事情(其中in子句包含codeIds参数中的所有值):

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

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

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

问题是,我不能dynamic生成一个“OR”子句的列表,因为它们是在编译时设置的。

如何使用Linq to Sql来完成检查列的where子句是否在dynamic值列表中?

使用

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

你也可以使用:

 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; 

我在Jon Skeet的回答中一直使用这个方法,但是另外一个使用了ConcatConcat方法在有限的testing中performance稍微好一些,但是这很麻烦,我可能会坚持使用Contains ,或者我会写一个帮助器方法来为我做这个。 无论哪种方式,如果有人感兴趣,还有另一种select:

方法

 // 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 ); } 

性能testing

这不是遥远的科学。 我想象你的数据库结构和列表中包含的ID的数量将会产生重大的影响。

我build立了一个testing,我做了100个试验,每个ConcatContains ,每个试验包括select由主键随机列表指定的25行。 我已经运行了十几次了, Concat方法大部分时间出来的速度提高了5-10%,虽然有一次Contains方法只是一个smidgen。

  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();