entity framework以一对多替换集合的正确方法

假设客户有许多电话号码,而电话号码只有一个客户。

public class PhoneNumber : IValueObject { public string Number {get; set;} public string Type {get; set;} } public class Customer : IEntity { public ICollection phones {get; private set;} //ew at no encapsulated collection support public void SetPhones(params PhoneNumber[] phones) { this.phones.Clear(); this.phones.AddRange(phones); } } 

如果我像这样进行EF映射并运行它,每次我设置电话号码时,它将创建新的PhoneNumbers但不删除旧的。 没有其他实体引用电话号码,我甚至没有在我的dbcontext上公开它,有没有办法告诉EF Customer完全拥有PhoneNumbers ,因此如果从集合中删除了电话号码,他们应该被删除?

证明

我意识到有十几种方法来解决这个问题,但这不是一个奇怪的边缘情况,处理这个问题的“正确”方法是什么。

我有完全相同的问题:)

关于识别关系的答案解决了我的问题。

注意:您必须加载集合(热切,明确或懒惰),以便在设置新值和调用save之前跟踪它。 否则你不会更换集合,只是添加它。

例如:

 var entity = unitOfWork.EntityRepository.GetById(model.Id); // I have something like this to load collection because // I don't have the collection's entities exposed to the context unitOfWork.EntityRepository.LoadCollection(entity, e => e.CollectionProperty); entity.CollectionProperty = newCollectionValuesList; unitOfWork.Save(); 

这将从“集合表”中删除以前的集合值,并仅添加新设置的值。

希望有所帮助。

第一(可选):

我建议你做

public ICollection phones {get; private set;}

一个virtual属性,让Entity Framework知道它应该是延迟加载的(即使你没有启用Lazy Load ,这是一个很好的做法)。

public virtual ICollection phones {get; private set;}

第二

PhoneNumber类上添加一个反向导航属性 (为了实现我在下面给出的解决方案,将需要它):

 public class PhoneNumber : IValueObject { public string Number {get; set;} public string Type {get; set;} public virtual Customer {get; set;} } public class Customer : IEntity { public ICollection phones {get; private set;} //ew at no encapsulated collection support public void SetPhones(params PhoneNumber[] phones) { this.phones.Clear(); this.phones.AddRange(phones); } } 

第三(可能解决您的问题):

从Context中删除PhoneNumber对象,而不是从Customer删除:

 public ICollection phones {get; private set;} //ew at no encapsulated collection support public void SetPhones(params PhoneNumber[] phones) { Context.PhoneNumbers.RemoveRange(this.phones); this.phones.AddRange(phones); } }