如何确保在使用存储库模式和entity framework时创build代理?

我在SurveyController类中有这个方法:

public ActionResult AddProperties(int id, int[] propertyids, int page = 1) { var survey = _uow.SurveyRepository.Find(id); if (propertyids == null) return GetPropertiesTable(survey, page); var repo = _uow.PropertySurveyRepository; propertyids.Select(propertyid => new PropertySurvey { //Setting the Property rather than the PropertyID //prevents the error occurring later //Property = _uow.PropertyRepository.Find(propertyid), PropertyID = propertyid, SurveyID = id }) .ForEach(x => repo.InsertOrUpdate(x)); _uow.Save(); return GetPropertiesTable(survey, page); } 

GetPropertiesTable重新显示属性但PropertySurvey.Property被标记为虚拟的,并且我使用new运算符创build了实体,因此从未创build用于支持延迟加载的代理,并且在访问它时为空。 当我们直接访问DbContext时,我们可以使用Create方法来显式创build代理 。 但是我在这里有一个工作单元和存储库模式。 我想我可以公开context.Create方法通过一个repository.Create方法,然后我需要记住,当我添加一个实体时使用,而不是新的运算符。 但是,将问题封装在我的InsertOrUpdate方法中不是更好吗? 有什么方法可以检测出被添加的实体在代理时不是代理吗? 这是我的基本库类中的InsertOrUpdate方法:

  protected virtual void InsertOrUpdate(T e, int id) { if (id == default(int)) { // New entity context.Set<T>().Add(e); } else { // Existing entity context.Entry(e).State = EntityState.Modified; } } 

基于qujck提供的答案。 这里是你如何做到这一点,而不必采用automapper:

编辑总是检查代理 – 不只是在插入 – 如评论中所build议的

再次编辑以使用不同的方法来检查代理是否被传入方法。 改变这种技术的原因是当我引入一个从另一个inheritance的实体时遇到了问题。 在这种情况下,一个inheritance的实体可能会失败entity.e.GetType().Equals(instance.GetType()检查,即使它是一个代理。我从这个答案得到了新的技术

 public virtual T InsertOrUpdate(T e) { DbSet<T> dbSet = Context.Set<T>(); DbEntityEntry<T> entry; if (e.GetType().BaseType != null && e.GetType().Namespace == "System.Data.Entity.DynamicProxies") { //The entity being added is already a proxy type that supports lazy //loading - just get the context entry entry = Context.Entry(e); } else { //The entity being added has been created using the "new" operator. //Generate a proxy type to support lazy loading and attach it T instance = dbSet.Create(); instance.ID = e.ID; entry = Context.Entry(instance); dbSet.Attach(instance); //and set it's values to those of the entity entry.CurrentValues.SetValues(e); e = instance; } entry.State = e.ID == default(int) ? EntityState.Added : EntityState.Modified; return e; } public abstract class ModelBase { public int ID { get; set; } } 

我同意你的意见,这应该在一个地方处理,最好的地方,抓住所有看起来是你的存储库。 您可以将T的types与上下文创build的实例进行比较,如果types不匹配,则可以使用类似Automapper的类来快速传输所有值。

 private bool mapCreated = false; protected virtual void InsertOrUpdate(T e, int id) { T instance = context.Set<T>().Create(); if (e.GetType().Equals(instance.GetType())) instance = e; else { //this bit should really be managed somewhere else if (!mapCreated) { Mapper.CreateMap(e.GetType(), instance.GetType()); mapCreated = true; } instance = Mapper.Map(e, instance); } if (id == default(int)) context.Set<T>().Add(instance); else context.Entry(instance).State = EntityState.Modified; }