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;
        }

EF:在n层应用中,如何修改数据库中已有的条目

而不是调用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);