有效加入内存列表

Ada*_*gen 7 c# sql linq performance entity-framework

在EF中,如果我有一个灵长类型列表(List),那么对表的"加入"很容易:

var ids = int[]{1,4,6}; //some random values
var rows = context.SomeTable.Where(r => ids.Contains(r.id))
Run Code Online (Sandbox Code Playgroud)

在您想要加入多个列的瞬间,这会变得更加复杂:

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
Run Code Online (Sandbox Code Playgroud)

我找到了两种方法来加入它,但两者都不是很好:

  1. 吮吸整个表,并根据其他数据对其进行过滤.(如果表格非常大,这会变慢)
  2. 对于每个键,查询表(如果你有相当数量的行可以拉慢)

有时,我能够做出的妥协是修改#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
}
Run Code Online (Sandbox Code Playgroud)

但即便如此,这也可能会导致数据过多.

我知道有一些方法可以将表值参数哄骗到ADO.Net中,以及我可以构建一系列OR一起使用的.Where()子句的方法.有没有人有魔法子弹?

Lau*_*nce 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);
}
Run Code Online (Sandbox Code Playgroud)

我已经在 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));
Run Code Online (Sandbox Code Playgroud)

不幸的是,我在这台笔记本电脑上没有 EF,甚至无法测试这在语法上是否正确。

我也不知道它的性能如何,如果它真的有效的话......