Entity Framework Core を使っていて、 エンティティをまとめて更新したい場面は結構あるが、 タイプセーフかつ効率的に更新する手段は、 今のところ標準で提供されていない。
ExecuteSqlCommand を使って直接 SQL を発行すればいいんだけど、 テストではInMemoryプロバイダーを使用しているので、 一括更新だけ違うやり方でテストしなければいけなくなるのが面倒。
そこで Entity Framework Plus を使ってみることにした。 Entity Framework と Entity Framework Core の機能を拡張できるライブラリ。
Entity Framework Core 用のパッケージを使う。
IQueryable
var publishedAt = DateTimeOffset.UtcNow; var query = from e in context.Entries join b in context.Blogs on e.BlogId equals b.Id where e.TenantId == tenantId where b.UserId == userId where e.IsDraft select e; await query.UpdateAsync(e => new Entry() { IsDraft = false, PublishedAt = publishedAt, });
普通に使うぶんにはこれでOK。 ただ注意点があって、テストで InMemory プロバイダーを使っていると
UpdateAsync results in Unable to cast object of type 'Microsoft.EntityFrameworkCore.Query.Internal.InMemoryQueryContextFactory'
という例外が発生してしまう。 その場合は
BatchUpdateManager.InMemoryDbContextFactory = () => new ApplicationDbContext(options);
という風に、Entity Framework Plus に DbContext を取得するためのデリゲートを登録しておくことで回避可能。