2

当 Entity Framework 为与多对多关系表连接的两个数据库表(比如说 Table1 和 Table2)生成 ObjectContext 时,它不会为外部参照表创建对象,而是选择在任一端的集合属性关系。所以在 Table1 你有EntityCollection<Table2> Table2s,在 Table2 你有EntityCollection<Table2> Table1s. 在大多数情况下,这实际上非常棒......

但是,在这种情况下,我有一个整数列表,表示应该在 Table1.Table2s 集合中的 Table2 行的数据库 ID。

我看不到使用实体键设置该集合的任何方法,所以我坚持将它们选择到 ObjectContext 中,这已经是无缘无故要做的大量工作。我让自己希望 LINQ-to-Entities 能够智能地推迟执行并像我想要的那样在 SQL 服务器上执行它(尽管我的 Where 使用包含,它可能会或可能不会正确转换为 SQL 中的 IN())。所以我可以做到:

table1instance.Table2s.Clear();
var table2sToInclude = context.Table2s.Where(
  t => 
  listOfTable2DatabaseIds.Contains(t.Id));

但是没有EntityCollection<T>.AddRange(IEnumerable<T>)或没有,IEnumerable<T>.ToEntityCollection<T>()当然也没有扩展方法,所以我现在不知道如何处理这些结果。我能做的就是

foreach (var table2 in table2sToInclude)
{
  table1instance.Table2s.Add(table2);
}

这看起来很荒谬,我知道会迫使很多不必要的评估。

有没有一种“正确的”,或者,也许是“不那么蹩脚”的方式来做到这一点?

4

1 回答 1

2

没有 EF 不会推迟任何查询执行。没有什么像从选择中插入一样。Linq-to-entities 只是查询语言,查询的职责是执行。它与 EF 本身提供的持久性功能严格分开。

如果要在 table1 中的现有项目和 table2 中的退出项目之间创建关系,可以使用如下代码:

using (var ctx = new YourContext())
{
    var table1 = new Table1 { Id = 123 };
    ctx.Table1s.Attach(table1);

    foreach (var table2 in table2sToInclude.Select(id => new Table2 { Id = id }))
    {
        ctx.Table2s.Attach(table2);
        order.Table2s.Add(table2);
    }
    ctx.SaveChanges();
}

此代码在 ID 为 123 的 Table1 的项目与 table2sToInclude 中的所有 Table2 的项目之间创建关系,而无需从数据库中加载任何单个记录。

What makes adding records one by one "lame"? Do you understand what is benefit of AddRange? AddRange in typical collection extends capacity of internal array and just copy items to extended array. EntityCollection is not typical array and it must process each added entity. So even if there will be some AddRange it will internally iterate items and process them on by one.

于 2011-05-30T20:27:47.363 回答