linq to entities-如何在Entity Framework中有效地设置多对多EntityCollectio



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

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

我看不出有任何方法可以使用实体键来设置该集合,所以我一直在ObjectContext中选择这些键,这已经是一项毫无理由的大量工作了。我希望LINQ to Entities能够智能地推迟执行,并像我希望的那样在SQL服务器上执行所有操作(尽管我的Where使用Contains,它可能会也可能不会正确地转换为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);
}

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

有没有一种"正确"的方法,或者说,"不那么蹩脚"的方法来做到这一点?

没有EF不会推迟任何查询执行。没有什么能比得上select中的insert。Linq-to实体只是查询语言,查询的职责是执行。它与EF本身提供的持久性功能是严格分离的。

如果你想在表1中的现有项目和表2中的现有项目之间创建关系,你可以使用这样的代码:

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的表1的项和table2sToInclude中表2的所有项之间的关系,而不从数据库加载任何单个记录。

是什么让一个接一个地添加记录变得"蹩脚"?你知道AddRange的好处是什么吗?典型集合中的AddRange扩展了内部数组的容量,只将项复制到扩展数组中。EntityCollection不是典型的数组,它必须处理每个添加的实体。因此,即使会有一些AddRange,它也会在内部迭代项目并逐个处理它们。

相关内容

  • 没有找到相关文章

最新更新