简体   繁体   English

更新实体框架中的特定字段

[英]Update specific fields in Entity Framework

I have a model:我有一个 model:

public class VR
{
    [Key]
    public int ID { get; set; }
    public string FullName { get; set; }
    public string CreatedBy { get; set; }
    public DateTime? Created { get; set; }
    public string ModifiedBy { get; set; }
    public DateTime? Modified { get; set; }
}

My controller's Edit function:我的控制器Edit function:

    // POST: VRs/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(VR vR)
    {
        if (ModelState.IsValid)
        {
            var Result = (from c in _context.MyVR.Where(c => c.ID == vR.ID) select c).Single();

            vR.Created = Result.Created;
            vR.CreatedBy = Result.CreatedBy;
            vR.ModifiedBy = User.Identity.Name;
            vR.Modified = DateTime.Now;
        
            _context.Update(vR);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(vR);
    }

and I get the error below:我收到以下错误:

The instance of entity type ' UNTest.ViewModels.VR ' cannot be tracked because another instance of this type with the same key is already being tracked.无法跟踪实体类型“ UNTest.ViewModels.VR ”的实例,因为已跟踪具有相同键的该类型的另一个实例。 For new entities consider using an IIdentityGenerator to generate unique key values.对于新实体,请考虑使用IIdentityGenerator生成唯一键值。

You can Attach the entity to avoid loading it from DB (save performance) and update only the fields you want. 您可以附加实体以避免从DB加载(保存性能)并仅更新所需的字段。

This also avoids the problem of your code when you load an instance from the DB ( Result ) and track another instance with the same Id ( vR ) resulting in an exception. 当您从DB( Result )加载实例并跟踪具有相同Id( vR )的另一个实例时,这也可以避免代码问题,从而导致异常。

// POST: VRs/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(VR vR)
    {
        if (ModelState.IsValid)
        {
            //Attach the instance so that we don't need to load it from the DB
            _context.MyVR.Attach(vR);

            vR.ModifiedBy = User.Identity.Name;
            vR.Modified = DateTime.Now;

            //Specify the fields that should be updated.
            _context.Entry(vR).Property(x => x.ModifiedBy).IsModified = true;
            _context.Entry(vR).Property(x => x.Modified).IsModified = true;

            _context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(vR);
    }

The other way to specify fields that should not be updated. 另一种指定不应更新的字段的方法。

// POST: VRs/Edit/5
        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Edit(VR vR)
        {
            if (ModelState.IsValid)
            {
                //Attach the instance so that we don't need to load it from the DB
                _context.Entry(vR).State = EntityState.Modified; 

                vR.ModifiedBy = User.Identity.Name;
                vR.Modified = DateTime.Now;

                //Specify the fields that should not be updated.
                _context.Entry(vR).Property(x => x.Created).IsModified = false;
                _context.Entry(vR).Property(x => x.CreatedBy).IsModified = false;

                _context.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(vR);
        }

In case you use a view model, you can use new operator to create your data model and copy the fields you want to update: 如果您使用视图模型,则可以使用new运算符创建数据模型并复制要更新的字段:

// POST: VRs/Edit/5
            [HttpPost]
            [ValidateAntiForgeryToken]
            public IActionResult Edit(VRViewModel vRVM)
            {
                if (ModelState.IsValid)
                {
                    VR vR = new VR();
                    //Attach the instance so that we don't need to load it from the DB
                    _context.MyVR.Attach(vR);

                    //Set the Id for your model.
                    vR.Id = vRVM.Id;
                    //Let's say you also want to update this field from the VM
                    vR.FullName = vRVM.FullName;

                    vR.ModifiedBy = User.Identity.Name;
                    vR.Modified = DateTime.Now;

                    //Specify the fields that should be updated.
                    _context.Entry(vR).Property(x => x.ModifiedBy).IsModified = true;
                    _context.Entry(vR).Property(x => x.Modified).IsModified = true;
                    _context.Entry(vR).Property(x => x.FullName).IsModified = true;

                    _context.SaveChanges();
                    return RedirectToAction("Index");
                }
                //create your new view model and return it. For demonstration purpose, I return the same view model, in your real code, you can adjust it.
                return View(vRVM);
            }

You have retrieved the data entity from the context so its being tracked. 您已从上下文中检索数据实体,以便跟踪它。 You cannot then track another entity with the same ID in the same context. 然后,您无法在同一上下文中跟踪具有相同ID的另一个实体。

Change the POST method to update the data model from the view model, and save the data model 更改POST方法以从视图模型更新数据模型,并保存数据模型

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(VR vR)
{
    if (ModelState.IsValid)
    {
        var result = (from c in _context.MyVR.Where(c => c.ID == vR.ID) select c)
           .FirstOrDefault(); // use FirstOrDefault() to prevent an exception if the user changes you input for the ID.
        if (result != null)
        {
           result.FullName = vR.FullName;
           result.ModifiedBy = User.Identity.Name;
           result.Modified = DateTime.Now;
           _context.Update(result);
           _context.SaveChanges();
            return RedirectToAction("Index");
        }
    return View(vR);
}

I am late to the party, but.我参加聚会迟到了,但是。 Copied below code from above answer.从上面的答案复制下面的代码。

// POST: VRs/Edit/5. // POST: VRs/Edit/5.

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(VR vR)
{
    if (ModelState.IsValid)
    {
        //Attach the instance so that we don't need to load it from the DB
        _context.MyVR.Attach(vR);

        //vR.ModifiedBy = User.Identity.Name;
        //vR.Modified = DateTime.Now;
        _context.MyVR.Attach(vR).State = EntityState.Modified;
        //Specify the fields that should be updated.
        _context.Entry(vR).Property(x => x.ModifiedBy).IsModified = true;
        _context.Entry(vR).Property(x => x.Modified).IsModified = true;

        _context.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(vR);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM