使用实体框架4选择具有非标量键列表的多行的好方法

本文关键字:列表 方法 标量 框架 实体 选择 | 更新日期: 2023-09-27 18:07:26

我正在使用EF 4,我试图找到一个好方法来选择记录,其中主键使用多列并使用对象列表进行搜索。以下是我到目前为止所做的尝试,但都没有成功:

我有一个Foo类型的对象列表。Foo有两个属性A和b。Order表上的主键是A和b列。

var orders = (from o in context.Orders
              where FooList.Contains(new Foo { A = o.A, B = o.B }
              select o);

这会抛出一个错误,认为我只能使用标量值。据我所知,我需要一个标量列表来表示傻瓜。我也尝试加入我的对象列表,但也没有工作:

var orders = (from o in context.Orders
              join foo in FooList
              on new { foo.A, foo.B } equals new { o.A, o.B }
              select o)

显然,我可以在傻瓜中迭代所有的值,得到我需要的顺序并更新它,但这在我目前的情况下非常缓慢(傻瓜中大约有6000个值)。

任何想法?

使用实体框架4选择具有非标量键列表的多行的好方法

您应该仍然能够使用(一个变体)BuildContainsExpression解决方案,这在EF 4之前是必要的。

结果SQL将是相同的

您可能必须在查询中"缩放"组合键以将键映射到唯一的标量。例如:假设您的属性AB是字符串:

var orders = (from o in context.Orders
              where FooList.Select(f => f.A + ";" + f.B)
                  .Contains(o.A + ";" + o.B)
              select o);

(当然,这个标量通常不能保证是唯一的,但是如果您知道您的字符串AB永远不能包含分号,那么它可能仍然是好的。)您必须注意Contains中的表达式可以转换为SQL(在这个字符串连接的示例中可以工作)。

我们应该能够通过修改表达式树来实现这一点。我们想要有效地将表达式树转换为sql,如下所示:

Where
(
   (Foo.A == "A" && foo.B == 1)
|| (Foo.A == "B" && foo.B == 2)
)

因此,如果我们使用Contains语法,并在幕后使用表达式访问器来遍历树并替换表达式,我们应该得到我们想要的。

不幸的是,我对LINQ表达式树没有足够深入的了解,无法快速提出解决方案。

我看到的大多数例子都严格地处理修改表达式树来处理标量值(List.Contains)或使用表达式树来生成自己的SQL用于批量操作执行