在EF中,如果我有一个灵长类动物列表(列表),那么对表的“加入”很容易:
var ids = int[]{1,4,6}; //some random values
var rows = context.SomeTable.Where(r => ids.Contains(r.id))
在您希望加入多个列的瞬间,这会变得更加复杂:
var keys = something.Select(s => new { s.Field1, s.Field2 })
var rows = context.SomeTable.Where(r => keys.Contains(r => new { s.Field1, s.Field2 })); // this won't work
我找到了两种加入它的方法,但两者都不是很好:
有时,我能够做出的妥协是修改后的#1:基于一个相当独特的密钥拉入表的子集
var keys = something.Select(s => s.Field1)
var rows = context.SomeTable.Where(r => keys.Contains(s.Field1)).ToList();
foreach (var sRow in something)
{
var joinResult = rows.Where(r => r.Field1 == sRow.Field1 && r.Field2 == sRow.Field2);
//do stuff
}
但即使这样也可以撤回太多数据。
我知道有一些方法可以将表值参数引入ADO.Net,以及我可以构建一系列OR一起的.Where()子句的方法。有没有人有魔法子弹?
答案 0 :(得分:0)
您可以尝试展平您的密钥,然后使用相同的Contains
模式。虽然您可以使用函数索引将展平的密钥存储在数据库中,但这对大型查询可能不会很好...
我使用列K1 int, K2 int, Name varchar(50)
var l = new List<Tuple<int, int>>();
l.Add(new Tuple<int, int>(1, 1));
l.Add(new Tuple<int, int>(1, 2));
var s = l.Select(k => k.Item1.ToString() + "," + k.Item2.ToString());
var q = Tests.Where(t => s.Contains(t.K1.ToString() + "," + t.K2.ToString()));
foreach (var y in q) {
Console.WriteLine(y.Name);
}
我在LinqPad中用Linq to SQL
测试了这个首次尝试不起作用:
我认为将其作为单个查询编写的方式就是这样的
var keys = something.Select(s => new { s.Field1, s.Field2 })
var rows = context.SomeTable.Where(r => keys.Any(k => r.Field1 == k.Field1 && r.Field2 == k.Field2));
不幸的是我在这台笔记本电脑上没有EF,甚至无法测试这是否在语法上正确。
如果它起作用的话,我也不知道它是多么高效......
答案 1 :(得分:0)
而不是.Contains(),你如何使用内连接并以这种方式“过滤”:
from s in context.SomeTable
join k in keys on new {k.Field1, k.Field2} equals new {s.Field1, s.Field2}
上面可能有拼写错误,但你明白了......
答案 2 :(得分:0)
var rows =
from key in keys
join thingy in context.SomeTable
on 1 = 1
where thingy.Field1 == key && thingy.Field2 == key
select thingy
应该工作,并生成合理的SQL
答案 3 :(得分:0)
我遇到了完全相同的问题,我提出的解决方案是:
看起来像这样:
var unique1 = something.Select(x => x.Field1).Distinct().ToList();
var unique2 = something.Select(x => x.Field2).Distinct().ToList();
var priceData = rows.Where(x => unique1.Contains(x.Field1) && unique2.Contains(x.Field2));
下一个是我自己的解决方案,我称之为BulkSelect,其背后的想法是这样的: