EFCoreのTimestampを使って楽観的排他制御をやってみます。
実行環境
- VS2022 17.6.5
- EFCore 7.0.10
- SQL Server 2022
Entityを用意する
次のようなEntityを用意しました。
public record Todo { public int Id { get; set; } public string? Content { get; set; } public DateTime Created { get; set; } public DateTime? Updated { get; set; } public DateTime? Deleted { get; set; } [Timestamp] public byte[] Version { get; set; } = null!; }
楽観的排他制御のためにVersionというプロパティを用意し、Timestamp属性をつけておきます。 テスト用のデータを入れておきました。
適当なカラムを更新する
コマンド引数で指定した時間だけ実行を遅らせるようにして、プログラムを同時に実行するようにします。
var dbContext = new AppDbContext(); if (!int.TryParse(args.FirstOrDefault(), out var delay)) { delay = default; } var todo = await dbContext.Todos.FirstAsync(); todo.Content = "ガチアサリ"; await Task.Delay(delay); await dbContext.SaveChangesAsync();
実行してみる
複数のターミナルから'dotnet run'をババっと実行してみます。ドキュメントによるとDbUpdateConcurrencyExceptionが発生するそうですがどうでしょう。
Unhandled exception. Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: The database operation was expected to affect 1 row(s), but actually affected 0 row(s); data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
無事?DbUpdateConcurrencyExceptionが発生しました。