我正在尝试更好地了解UoW模式,因为我喜欢它的概念,但目前我很难节省实体。
问题是当我的控制器中的编辑(POST)操作触发时,只保存父实体并且子实体完好无损,即我收到以下错误:
附加“Access.Models.ApplicationParameter”类型的实体 失败,因为同一类型的另一个实体已经相同 主键值。使用“附加”方法或时,可能会发生这种情况 将实体的状态设置为“未更改”或“已修改”(如果有) 图中的实体具有冲突的键值。这可能是因为 某些实体是新的,尚未收到数据库生成的密钥 值。在这种情况下,使用“添加”方法或“已添加”实体状态 跟踪图形,然后将非新实体的状态设置为 “视情况而定”或“修改”。
注意:父实体应用可以有多个子 ApplicationParameter 实体。
控制器
[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);
}
}
问题:如何保存这些子实体?
答案 0 :(得分:1)
确保您建立applicationParameter
和application
之间的关系。使用导航属性或ID至少有三种方法可以做到这一点,我在代码中看不到这样的一行:
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
。
答案 1 :(得分:1)
就我看来,你有两个选择。
最简单的方法是在Edit操作开始时获取实体。如果结果为null,则添加新值,否则使用新值更新实体并保存。这将确保父实体和所有子项处于相同的上下文中。
另一种方法是使用自我跟踪实体。看看Self Tracking Entities。这样您就可以处理实体的状态而不是EF。
问题是你只是将父级的状态设置为更新,每个子状态仍然被添加,所以它试图添加子实体而不是更新它们。