EF:在n层应用中,如何修改数据库中已有的条目
本文关键字:数据库 修改 何修改 应用 EF | 更新日期: 2023-09-27 18:09:34
我可能不是EF专家,但我对它有一个问题:)。
我做n层业务应用程序,所以我在我的应用程序中有服务代码和存储库代码。在我的服务代码中,它读取现有的用户实体,我做一些属性更新,它调用存储库的方法Edit。出现错误:
附加类型的实体"MobileWallet.Common.Repository。MwbeUserData'失败,因为另一个同一类型的实体已经具有相同的主键值。这可能发生在使用"附加"方法或设置如果图中的任何实体已更改,则将实体更改为"未更改"或"已修改"键值冲突。这可能是因为一些实体是新的和尚未收到数据库生成的键值。在这种情况下使用"添加"方法或"添加"实体状态来跟踪图形和然后将非新实体的状态设置为"Unchanged"或"Modified"合适。
我的编辑方法是这样的:
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:有没有好的教程来了解如何使用EF与业务n层应用程序?
谢谢你的回答。
更新1:新发现:
In Repository Edit method:
Context.ChangeTracker.Entries().ToList()[1].CurrentValues["Firstname"] = "AAA"
Context.ChangeTracker.Entries().ToList()[1].OriginalValues["Firstname"]= "AAA"
但是CurrentValue应该是BBB,为什么不更新?它是在调用Respority code的Service code中更新的,更新后的实体被传递给Repository Edit方法。
更新2:更多关于我的架构:我有3层控制器(WEB API),服务和存储库。所以我的Service方法update是这样的:
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;
}
而不是调用Context.Entry(entityToUpdate)
并将其状态设置为modified,您可以搜索您想要更新和修改其成员的实体。然后将其状态设置为modified,如下所示。
同样在Edit函数中,您应该明确列出要更新的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中的变化跟踪器。扩展并通过更新实体CurrentValues修复了这一行。
Entities.Entry(c).CurrentValues.SetValues(company);