假设:
List<int> myList;
如果我想返回此列表中包含记录ID的数据,我只会这样做:
var q = db.Table.Where(c=> myList.Contains(c.ID));
然而,鉴于:
List<Tuple<int, int>> myList;
如何编写Linq查询以返回满足两个条件的记录?有一个数据点我会写:
var q = db.Table.Where(c=>
c.ID == myList.Item1
&& c.AnotherValue == myList.Item2);
如何将上述语句转换为List<Tuple<int, int>>
?
答案 0 :(得分:6)
Tuple
是一个无法由Linq Provider转换为sql的结构。解决方案可能是切换到Linq to Objects
var q = db.Table.AsEnumerable()
.Where(c=> myList.Any(tuple => c.ID == tuple.Item1 &&
c.AnotherValue == tuple.Item2));
但是这个解决方案的坏处是你要从该表加载所有行来过滤内存。
另一种解决方案可能是使用Linqkit:
var predicate = PredicateBuilder.False<Table>();
foreach (string t in myList)
{
predicate = predicate.Or(c =>c.ID == t.Item1 && c.AnotherValue == t.Item2));
}
db.Table.AsExpandable().Where(predicate);
您可以在此link
中找到有关此最后一个解决方案的更多信息答案 1 :(得分:1)
var q = db.Table.AsEnumerable().Where(c => myList.Any(tuple => c.ID == tuple.Item1 &&
c.AnotherValue == tuple.Item2));
使用Any
,您可以检查myList
中是否至少有一个元素符合您的条件。
但正如@octaviocci指出的那样,这不能转换为SQL,因此您需要先调用AsEnumerable()
并在本地进行过滤,如果存在大量不相关的记录,这可能不是您想要的
答案 2 :(得分:0)
以下是一些示例代码,说明了一种方法:
DataTable dt = new DataTable("demo");
// hydrate your table here...
List<Tuple<int, int>> matches = new List<Tuple<int, int>>();
Func<List<Tuple<int,int>>, DataRow, bool> RowMatches = (items, row) => {
var rowValue1 = (int)row["Id"];
var rowValue2 = (int)row["SomeOtherValue"];
return items.Any(item => item.Item1 == rowValue1 && item.Item2 == rowValue2);
};
var results = dt.Rows.Cast<DataRow>().Where(r => RowMatches(matches, r));
Console.WriteLine(results.Any());
答案 3 :(得分:0)
见下面的代码:
List<Tuple<int, int>> myList;
var set = new HashSet(myList);
var q = db.Table.AsEnumerable().Where(c=> set.Contains(new Tuple(c.ID, c.AnotherValue)));
请注意,哈希集用于优化大Where
的{{1}}子句的执行。
答案 4 :(得分:0)
由于Tuple
无法使用Linq to Entities
,您可以尝试这样的事情:
List<int> items1 = myList.Select(t => t.Item1).ToList();
List<int> items2 = myList.Select(t => t.Item2).ToList();
var q = db.Table.GroupBy(m => { m.ID, m.AnotherValue })
.Where(g => items1.Contains(g.Key.ID) &&
items2.Contains(g.Key.AnotherValue))
.SelectMany(g => g);