自分はORMではS2JDBCの洗礼を浴びていて、静的な型がついているEntityをRDBにMappingしてくれるORMが好きだ。
最近ではEntity Framework Coreが良くて、ちょっと前から使っているシステムがある。
唐突にそれでやっている工夫を書きたくなったので書く。
タイトルの通りあるEntityの生成時刻と更新時刻をアプリケーションプログラムで付与するものだ。
確認してみたらバージョンは 2.0.x
だった。2つほどマイナーバージョンを置いて行かれている。大分変っているのだろうなぁ。
それはさておき。
まず、生成・更新時刻を付与したいEntityは以下の様なInterfaceを実装しておく。
public interface ITrackableEntity { DateTime UpdatedAt { get; set; } DateTime CreatedAt { get; set; } }
例えばこんな感じ。
public class BlobImage : ITrackableEntity { public int BlobImageId { get; set; } public string Path { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } }
後は、DBコンテキストのセーブ手前で変更があった ITrackableEntity に現在の時刻を設定してやる。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); } public override int SaveChanges() { AddTimestamps(); return base.SaveChanges(); } public override int SaveChanges(bool acceptAllChangesOnSuccess) { AddTimestamps(); return base.SaveChanges(acceptAllChangesOnSuccess); } public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken)) { AddTimestamps(); return await base.SaveChangesAsync(cancellationToken); } public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken)) { AddTimestamps(); return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken); } private void AddTimestamps() { DateTime time = DateTime.Now; var entries = ChangeTracker.Entries() .Where(entry => entry.Entity is ITrackableEntity) .ToList(); foreach (var entry in entries.Where(e => e.State == EntityState.Added)) { entry.Property("CreatedAt").CurrentValue = time; entry.Property("UpdatedAt").CurrentValue = time; } foreach (var entry in entries.Where(e => e.State == EntityState.Modified)) { entry.Property("CreatedAt").IsModified = false; entry.Property("UpdatedAt").CurrentValue = time; } } public DbSet<BlobImage> BlobImage { get; set; } }
私はこれでEntity Framework Core 2.0.x で CreatedAt, UpdatedAt を設定しました。
他にもやり方はあると思います。