ObjectContext.Attach
和ObjectSet.Attach
用于将一个分离的实体(已经存在于DB中)附加到上下文中-当ObjectContext时采用这种方式。SaveChanges被调用时,EF不尝试为这个附加的实体发送插入命令
但是我不理解EntityCollection.Attach
和EntityReference.Attach
的目的。也就是说,这两种方法只能附加已经由ObjectContext
管理的实体(因此它们不能用于附加EntityState
设置为Added
或Detached
的实体)。
由于由ObjectContext
管理的实体已经自动解决了它们的关系(即它们的EntityReference
属性返回一个父实体,它们的EntityCollection
属性包含相关的子实体),我无法理解通过使用EntityCollection.Attach
或EntityReference.Attach
将相关实体E1附加到特定实体E2,我们究竟会获得什么,因为E1已经由ObjectContext
自动附加到E2 ?
谢谢
作为一个例子,如果您在ObjectContext中有一个客户,并且您想要获得它客户的预订,您可以拨打以下电话:
myCust.Reservations.Load()
这将加载该客户的所有预订。但是,如果您想过滤这些预订,您可以在-中使用CreateSourceQuery相反,如下面的代码所示:
var customer=context.Contacts.OfType<Customer>().First();
var sourceQuery = customer.Reservations.CreateSourceQuery()
.Where(r => r.ReservationDate > new DateTime(2008, 1, 1));
customer.Reservations.Attach(sourceQuery);
该查询将在调用Attach方法时执行。现在,只有该客户的预订子集将从数据库中检索并具体化为对象。
你也可以使用CreateSourceQuery来筛选类型。在下面的代码中,Attach是与EntityReference一起使用,它不会接受IQueryable。相反,你需要传入一个对象,您可以使用FirstOrDefault查询方法获得该对象。自如果您尝试传入空值,Attach将抛出异常,您需要测试空值在调用Attach之前:
var addresses = context.Addresses.Take(5);
foreach (var a in addresses)
{
var sq = a.ContactReference.CreateSourceQuery()
.OfType<Customer>().FirstOrDefault();
if (sq != null)
a.ContactReference.Attach(sq);
}
在此代码中,只加载客户。