web-dev-qa-db-ja.com

EFCore、EntityState.Modifiedを使用してdbエントリを編集できません:「データベース操作は1行に影響するはずですが、実際には0行に影響します。」

ASP.NET MVC Core 1.0およびEntity Framework Core 1.0でIdentity Core 1.0を使用して、開始点として この記事 を使用して簡単なユーザー登録システムを作成し、ユーザーロールを追加しようとしています。ユーザーロールを追加できますが、編集することはできません。 EditRolesControllerアクションは次のとおりです。

_    [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();
        }
    }
_

対応するビューのフォームは次のとおりです。

_@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" />
}
_

新しいロール名はデータベースに保存されず、次の例外が発生します: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.

この正確なコード(EntityFrameworkCoreの代わりに_Microsoft.AspNet.Identity.EntityFramework_依存関係を使用)を使用して、EF 7、Identity 3などを使用してデータベースエントリを編集できました。

このコードがデータベースエントリの変更を許可しない理由についての考えはありますか?

12
jmk22

この背後に隠れたランダムな例外として隠れている隠れた例外がない限り、その理由は例外で明確に述べられています。

Idアクションで受け取ったroleオブジェクトのEditを確認し、データベースでそのIDを検索してみてください。表示される例外メッセージは、アタッチしたオブジェクトの一致するIDを持つ行を見つけることを期待していますが、そうではないため、更新するために一致する行を見つけることができなかったため、更新を実行できません。

編集:

エンティティを2回アタッチし、.Attach(role)の呼び出しを削除し、変更された状態でトラッキングコンテキストにオブジェクトを追加するのに十分な行をその下に保持します。

_//_db.Roles.Attach(role); //REMOVE THIS LINE !.
_db.Entry(role).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
_

エントリの状態を変更済みに設定すると、.SaveChanges()の呼び出し時にすべてのプロパティ値が更新されるため、特定のプロパティのみを更新する場合は this answer を参照してください。

これで問題が解決しない場合は、見逃している可能性のある内部例外を確認してください。例外メッセージが意味をなさないことがあり、内部例外で見つけることができる実際の問題を隠すことがあります。

4
Siraj Mansour

以下に示すように試すことができます。

_[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();
    }
}
_

注:

_db.Entry(role).State = EntityState.Modified;の場合

  • エンティティを__db_にアタッチするだけでなく、エンティティ全体をdirtyとしてマークします。
  • _db.SaveChanges()を実行すると、EFは_will update all the fields of the entity_というupdateステートメントを生成します。

_db.Roles.Attach(role)の場合

  • エンティティをコンテキストにアタッチしますdirtyとマークしません。
  • _db.Entry(role).State = EntityState.Unchanged;のようなものです。
  • 次に_update a property on the entity_に進まない限り、次回context.SaveChanges()を呼び出したときに、EF生成しないこのentityの_database update_。

i.e。データベースの更新を生成する必要がある場合、次のようにする必要があります。

__db.Roles.Attach(role); // State = Unchanged
role.RoleName = "Admin"; // State = Modified, and only the RoleName property is dirty
context.SaveChanges();
_
2
Sampath

更新または削除の実行後、EF Coreは影響を受けた行の数を読み取ります。

SELECT [ExampleEntityId]
FROM [ExampleEntities]
WHERE @@ROWCOUNT = 1 AND
[ExampleEntityId] = scope_identity();

エンティティにプライマリキーであるIdentityColumnがない場合、EF CoreはDbUpdateConcurrencyExceptionをスローします。

私の場合、データベースの関連テーブルに主キーを追加し(そしてそれらをIDとして設定します)。

1
Ahmet Arslan

あなたの答えは私にはうまくいきません。そして、私はこのようなエラーを解決しました。モデルクラスの割合の変更

[Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public string Id { get; set; }

マッピングクラスを変更した後

builder.Property(c => c.Id).HasColumnName("ID").IsRequired();

最後の変更は

 CustomerEntity thisrole = (from x in db.Customers
                          where x.Id == Id
                          select x).First();
            thisrole.Id = accountNum;
            thisrole.Name = name;
            thisrole.Phone = phone;
            thisrole.Email = email;
            thisrole.Address = address;
            db.SaveChanges();              
            return true;

このソリューションが誰かに役立つことを願っています。

1

テーブルにINSTEAD OF INSERTトリガーがある場合、データベースは操作をキャンセルし、EntityFrameworkはこのエラーを発生させます。

0
Sérgio Ferraz

私は2つの方法を組み合わせてこれを解決しました

var thisRole = _db.Roles.Where(r => r.Id.Equals(role.Id, 
StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
_db.Roles.Attach(thisRole);
thisRole.Name = role.Name;
_db.SaveChanges();
0
Minh Phuong

mysqlでは、AUTO_INCREMENT IDが必要です

このような:

他の机 wfdbcore201test.wftransitioninstance MODIFY COLUMN ID int(11)NOT NULL AUTO_INCREMENT FIRST;

0
fiyoung

ここで同じエラー、問題になったのは、更新のためにコードを再利用しながら挿入しています...

  Role role = new Role();
  role.Value = input;
  context.Add(role);                    
  await context.SaveChangesAsync();

挿入するときに変更する状態はありません...

0