0

我想知道UoW模式更好一点,因为我喜欢它的概念,但目前我有一个难以节省时间的实体。工作单位/存储库模式和更新实体使用EF

的问题是,当我的控制器火灾我的编辑(POST)操作只母公司获取保存和子实体是完整的,即我得到以下错误:

Attaching an entity of type 'Access.Models.ApplicationParameter' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

注:父实体应用程序可以有多个子实体应用程序参数实体。

控制器

[HttpPost] 
    public ActionResult Edit(ApplicationVM applicationVM) 
    { 
     Application application = ViewModelToModel(applicationVM); 
     uow.ApplicationRepository.Update(application); 

     foreach (var applicationParameterVM in applicationVM.ApplicationParameters) 
     { 
      ApplicationParameter applicationParameter = ViewModelToModel(applicationParameterVM); 

      bool exists = uow.ApplicationParameterRepository.Exists(applicationParameter.idApplicationParameter); 

      if (exists) 
      { 
       uow.ApplicationParameterRepository.Update(applicationParameter); 
      } 
      else 
      { 
       uow.ApplicationParameterRepository.Insert(applicationParameter); 
      } 
     } 

     uow.Save(); 
     return View(applicationVM); 
    } 

ApplicationParameterRepository.cs(刚刚更新片段)

public void Update(ApplicationParameter entity) 
    { 
     db.Entry(entity).State = EntityState.Modified; 
    } 

UOW.cs

public class UnitOfWork : IDisposable 
{ 
    private AMEntities db = null; 

    public UnitOfWork() 
    { 
     db = new AMEntities(); 
    } 

    //Add all the repository handles here 
    IApplicationRepository applicationRepository = null; 
    IApplicationParameterRepository applicationParameterRepository = null; 
    IApplicationUserRepository applicationUserRepository = null; 

    //Add all the repository getters here 
    public IApplicationRepository ApplicationRepository 
    { 
     get 
     { 
      if (applicationRepository == null) 
      { 
       applicationRepository = new ApplicationRepository(db); 
      } 
      return applicationRepository; 
     } 
    } 
    public IApplicationParameterRepository ApplicationParameterRepository 
    { 
     get 
     { 
      if (applicationParameterRepository == null) 
      { 
       applicationParameterRepository = new ApplicationParameterRepository(db); 
      } 
      return applicationParameterRepository; 
     } 
    } 
    public IApplicationUserRepository ApplicationUserRepository 
    { 
     get 
     { 
      if (applicationUserRepository == null) 
      { 
       applicationUserRepository = new ApplicationUserRepository(db); 
      } 
      return applicationUserRepository; 
     } 
    } 

    public void Save() 
    { 
     db.SaveChanges(); 
    } 

    private bool disposed = false; 

    protected virtual void Dispose(bool disposing) 
    { 
     if (!this.disposed) 
     { 
      if (disposing) 
      { 
       db.Dispose(); 
      } 
     } 
     this.disposed = true; 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 
} 

问题:我应该怎么做才能保存这些子实体?

回答

1

就我所见,您有2个选项。

  1. 最简单的事情就是在编辑操作开始时获取实体。如果结果为空,则添加一个新的值,否则使用新值更新实体并保存。这将确保父母实体和所有孩子处于相同的情境中。

  2. 另一种方式是使用自我跟踪实体。看看Self Tracking Entities。这样你就可以处理实体的状态而不是EF。

问题是你只设置父状态更新,每个孩子状态仍然被添加,所以它试图添加子实体而不是更新它们。

+0

这是正确的答案!忘了在这里发布解决方案,但#1是我如何解决它。问题是我从ViewModel获取没有所有信息的实体。 –

1

确保您建立了applicationParameterapplication之间的关系。至少有三种方法可以做到这一点使用导航属性或IDS,我不要在您的代码看到这样一行:

1.

// if application have unique Id, for example it already has been saved in db 
applicationParameter.ApplicationId = application.Id; 

2.

applicationParameter.Application = application; 

3.

//if application is a EF-generated proxy 
application.ApplicationParameters.Add(applicationParameter); 

此外,在简单的情况下,并不需要设置EntityState如果实体已被广告正确地处理上下文。

+0

我忽略了#1,因为这是在ViewModel本身内部完成的事情(idApplication直接传递给ViewModel)。我也尝试过#2,因为applicationParameter.Application之前是空的,但不幸的是没有帮助。 #3也没有帮助,因为它增加了已经添加的实体。 –

+0

@Agramer,你有自动增量字段'ApplicationParameter.Id'在数据库?如果否,则应在代码中手动设置“Id”。 –

+0

你让我走向正确的道路,谢谢!实际的问题是,而不是循环ViewModel的项目,我应该循环通过从ViewModel生成的父实体的项目。将在一分钟后发布解决方案。 –