我不是EF专家,但我有一个问题:)。
我正在进行n层业务应用程序,所以我的应用程序中有服务代码和存储库代码。在我的服务代码中,它读取现有的User实体,我更新了一些属性,并调用Repositiry的方法Edit。并出现错误:
附加类型的实体 'MobileWallet.Common.Repository.MwbeUserData'因为另一个而失败 相同类型的实体已具有相同的主键值。这个 使用“附加”方法或设置状态时可能会发生 如果图中的任何实体具有,则实体为“未更改”或“已修改” 冲突的关键值。这可能是因为一些实体是新的和 尚未收到数据库生成的键值。在这种情况下使用 “添加”方法或“已添加”实体状态可跟踪图表和 然后将非新实体的状态设置为“未更改”或“已修改”为 合适的。
我的编辑方法如下所示:
public override void Edit(MwbeUserData entityToUpdate)
{
LogChangeTrackerStateValues("UserUpdate starts");
if (Context.Entry(entityToUpdate).State == EntityState.Detached)
{
DbSet.Attach(entityToUpdate);
}
Context.Entry(entityToUpdate).State = EntityState.Modified;
//fix for User.Address problem
Context.Entry(entityToUpdate.Address).State = EntityState.Modified;
LogChangeTrackerStateValues("UserUpdate ends");
}
我也试过这样的代码:
public override void Edit(MwbeUserData entityToUpdate)
{
Context.Entry(entityToUpdate).State = EntityState.Modified;
//fix for User.Address problem
Context.Entry(entityToUpdate.Address).State = EntityState.Modified;
}
记录它所保留的内容保存在ChangeTracker
中 Context.ChangeTracker.Entries().ToList()[1]
但是Context.Entry(entityToUpdate).State = Detach for this object
。
问题1:如何解决这个问题?
问题2 :了解如何使用商务n层应用程序处理EF的任何好教程?
感谢您的回答。
更新1: 新发现:
在Repository Edit方法中:
Context.ChangeTracker.Entries().ToList()[1].CurrentValues["Firstname"] = "AAA"
Context.ChangeTracker.Entries().ToList()[1].OriginalValues["Firstname"]= "AAA"
但是CurrentValue应该是BBB,为什么不更新?它在服务代码中更新,调用Respority Code并将更新的实体传递给Repository Edit方法。
更新2:
关于我的架构的更多信息:我有3个版本Controler(WEB API),服务和存储库。所以我的服务方法更新如下所示:
public bool UpdateUser(MwbeUserUpdateIn userUpdateData)
{
MwbeReturnData<MwbeUserData> userData = repository.Get(userUpdateData.UserId);
// Determine if user exists
if (MwbeResponseCodes.NotFound == userData.Code)
{
return false;
}
MwbeUserData user = userData.Data;
// Check each field to be updated
if (!String.IsNullOrEmpty(userUpdateData.FirstName))
{
user.Firstname = userUpdateData.FirstName;
}
if (!String.IsNullOrEmpty(userUpdateData.MiddleName))
{
user.Middlename = userUpdateData.MiddleName;
}
if (!String.IsNullOrEmpty(userUpdateData.LastName))
{
user.Secondname = userUpdateData.LastName;
}
if (!String.IsNullOrEmpty(userUpdateData.MobileNumber))
{
user.Mobilenumber = userUpdateData.MobileNumber;
}
if (!String.IsNullOrEmpty(userUpdateData.Email))
{
user.Email = userUpdateData.Email;
}
if (null != userUpdateData.BirthDate)
{
user.BirthDate = (DateTime)userUpdateData.BirthDate;
}
// Update Addres fields
if (null != userUpdateData.Address)
{
if (!String.IsNullOrEmpty(userUpdateData.Address.City))
{
user.Address.City = userUpdateData.Address.City;
}
if (!String.IsNullOrEmpty(userUpdateData.Address.Country))
{
user.Address.Country = userUpdateData.Address.Country;
}
if (!String.IsNullOrEmpty(userUpdateData.Address.Street))
{
user.Address.Street = userUpdateData.Address.Street;
}
if (!String.IsNullOrEmpty(userUpdateData.Address.ZipCode))
{
user.Address.ZipCode = userUpdateData.Address.ZipCode;
}
}
// Save changes to DB
repository.Edit(ref user);
repository.SaveChanges();
return true;
}
答案 0 :(得分:1)
您可以搜索要更新的实体并修改其成员,而不是调用Context.Entry(entityToUpdate)
并将其设置为已修改状态。然后将其状态设置为已修改,如下所示。
同样在编辑功能中,您应该明确列出要更新的MwbeUserData
对象的哪些成员。这是一个安全问题,它会阻止某人过多地向控制器发布额外成员。
这是我使用的编辑功能的一个例子。
public ActionResult Edit([Bind(Include = "Id,CompanyName,Abbreviation,CompanyTypeRef")] Company company)
{
if (!ModelState.IsValid) return View(company);//error invalid state
var c = Entities.Set<Company>().FirstOrDefault(x => x.Id == company.Id);
if(c == null) return View(company);// error could not find entity
Entities.Entry(c).CurrentValues.SetValues(company);
Entities.Entry(c).State = EntityState.Modified;
Entities.SaveChanges();
return RedirectToAction("Edit", "Company", new { id = company.Id });
}
<强>更新强> 我有一个类似的问题,EntityFramework.Extented中的更改跟踪器未记录实体更改,并且通过使用此行更新实体CurrentValues来解决此问题。
Entities.Entry(c).CurrentValues.SetValues(company);