EF:如何在N层应用程序中修改DB中的现有条目

时间:2015-08-24 07:39:34

标签: c# entity-framework

我不是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;
        }

1 个答案:

答案 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);