当Entity Framework为与多对多关系表连接的两个数据库表(比如说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);
}
这似乎很荒谬,我知道会强制进行大量不必要的评估。
有没有“正确的”,或许,“不那么蹩脚”的方式来做到这一点?
答案 0 :(得分: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();
}
此代码在表1的id为123的项目与table2sToInclude的所有Table2项目之间创建关系,而不从数据库加载任何单个记录。
是什么让你逐一添加记录&#34; lame&#34;?你了解AddRange
的好处是什么?典型集合中的AddRange
扩展了内部数组的容量,只是将项目复制到扩展数组。 EntityCollection
不是典型的数组,必须处理每个添加的实体。因此,即使存在一些AddRange
,它也会在内部迭代项目并将其处理为一个。