ASP.NET MVC Core 1.0およびEntity Framework Core 1.0でIdentity 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();
}
}
_
対応するビューのフォームは次のとおりです。
_@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などを使用してデータベースエントリを編集できました。
このコードがデータベースエントリの変更を許可しない理由についての考えはありますか?
この背後に隠れたランダムな例外として隠れている隠れた例外がない限り、その理由は例外で明確に述べられています。
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 を参照してください。
これで問題が解決しない場合は、見逃している可能性のある内部例外を確認してください。例外メッセージが意味をなさないことがあり、内部例外で見つけることができる実際の問題を隠すことがあります。
以下に示すように試すことができます。
_[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)
の場合
_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();
_
更新または削除の実行後、EF Coreは影響を受けた行の数を読み取ります。
SELECT [ExampleEntityId]
FROM [ExampleEntities]
WHERE @@ROWCOUNT = 1 AND
[ExampleEntityId] = scope_identity();
エンティティにプライマリキーであるIdentityColumnがない場合、EF CoreはDbUpdateConcurrencyExceptionをスローします。
私の場合、データベースの関連テーブルに主キーを追加し(そしてそれらをIDとして設定します)。
あなたの答えは私にはうまくいきません。そして、私はこのようなエラーを解決しました。モデルクラスの割合の変更
[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;
このソリューションが誰かに役立つことを願っています。
テーブルにINSTEAD OF INSERTトリガーがある場合、データベースは操作をキャンセルし、EntityFrameworkはこのエラーを発生させます。
私は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();
mysqlでは、AUTO_INCREMENT IDが必要です
このような:
他の机 wfdbcore201test
.wftransitioninstance
MODIFY COLUMN ID
int(11)NOT NULL AUTO_INCREMENT FIRST;
ここで同じエラー、問題になったのは、更新のためにコードを再利用しながら挿入しています...
Role role = new Role();
role.Value = input;
context.Add(role);
await context.SaveChangesAsync();
挿入するときに変更する状態はありません...