我有一个函数,我得到一个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子句在动态值列表中?
答案 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数量会产生重大影响。
我设置了一个测试,其中我对Concat
和Contains
各进行了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)。