无法使用EFCore编辑数据库条目,EntityState.Modified:"数据库操作预计会影响1行,但实际上会影响0行."

jmk*_*k22 13 c# entity-framework asp.net-identity entity-framework-core asp.net-core

我正在使用Identity Core 1.0与ASP.NET MVC Core 1.0和Entity Framework Core 1.0创建一个简单的用户注册系统,以本文为出发点,我正在尝试添加用户角色.我可以添加用户角色,但我无法编辑它们.这是以下Edit行动RolesController:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Edit(IdentityRole role)
    {
        try
        {
            _db.Roles.Attach(role);
            _db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            return View();
        }
    }
Run Code Online (Sandbox Code Playgroud)

以下是相应视图中的表单:

@model Microsoft.AspNet.Identity.EntityFramework.IdentityRole
@{
    ViewBag.Title = "Edit";
}

<h2>Edit Role</h2>
<hr />
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.HiddenFor(model => model.Id)
    <div>Role name</div>
    <p>@Html.TextBoxFor(model => model.Name)</p>
    <input type="submit" value="Save" />
}
Run Code Online (Sandbox Code Playgroud)

新角色名称不保存到数据库,我得到以下异常: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded.

我能够使用这个确切的代码(使用Microsoft.AspNet.Identity.EntityFramework依赖项而不是EntityFrameworkCore)来使用EF 7,Identity 3等编辑数据库条目.

有关为什么此代码不允许修改数据库条目的任何想法?

Nei*_*rao 10

如果您尝试更新具有新相关实体的实体,也可能会发生这种情况。

例如,这段代码会抛出异常:

someEntity.AnotherEntity = new AnotherEntity();
dbContext.Update(someEntity);
dbContext.SaveChanges(); // Exception
Run Code Online (Sandbox Code Playgroud)

相反,请执行以下操作:

someEntity.AnotherEntity = new AnotherEntity();
dbContext.AnotherEntitySet.Add(someEntity.AnotherEntity);
dbContext.Update(someEntity);
dbContext.SaveChanges(); // No Exception
Run Code Online (Sandbox Code Playgroud)


Sam*_*ath 5

您可以尝试如下所示。

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Edit(IdentityRole role)
{
    try
    {
         _db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
        _db.SaveChanges();
        return RedirectToAction("Index");
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记 :

什么时候 _db.Entry(role).State = EntityState.Modified;

  • 您不仅将实体附加到_db,还将整个实体标记为dirty
  • 执行此操作时_db.SaveChanges(),EF 将生成一个update 声明will update all the fields of the entity

什么时候 _db.Roles.Attach(role)

  • 将实体附加到上下文而不将其标记为脏
  • 它就像_db.Entry(role).State = EntityState.Unchanged;.
  • 除非你再继续update a property on the entity,接下来你打电话时context.SaveChanges()EF 不会产生一个database update用于此entity

如果您需要生成数据库更新,您必须这样做:

_db.Roles.Attach(role); // State = Unchanged
role.RoleName = "Admin"; // State = Modified, and only the RoleName property is dirty
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)


Sir*_*our 5

除非有一个隐藏的异常作为愚蠢的随机异常隐藏在该异常的背后,否则在异常中明确说明原因。

Idrole您收到Edit操作中的对象时检查该对象,然后尝试在数据库中查找该ID。您看到的异常消息指出,它期望找到与您附加的对象的匹配ID匹配的行,但没有找到,因此更新失败,因为它找不到匹配的行来更新它。

编辑:

您将实体附加两次,删除.Attach(role)对它的调用,并保留在它下面的行,这足以将对象添加到处于修改状态的跟踪上下文中。

//_db.Roles.Attach(role); //REMOVE THIS LINE !.
_db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)

请注意,将条目的状态设置为Modifyed将在调用时更新所有属性值.SaveChanges(),因此,如果您只想更新某些属性,请参考此答案

如果这不能解决您的问题,请检查您可能错过的任何内部异常。有时,异常消息没有意义,并掩盖了您可能会在内部异常中找到的实际问题。