Entity Framework を使用して、SQL Server データベースの一時データを更新するための「汎用」メカニズムを実現しようとしています。
私がしたことは、ITemporalData
存在する必要がある 2 つのプロパティを定義するDateTime ValidFrom
とという「マーカー」インターフェイスを作成することDateTime? ValidTo
です。
public interface ITemporalData
{
DateTime ValidFrom { get; set; }
DateTime? ValidTo { get; set; }
}
私はDbContext.SaveChanges()
オーバーライドに「一般的な」アプローチを実装したいと考えていました。
- 任意のオブジェクトのクローン
ITemporalData
を作成します。これにより、新しいオブジェクトが保存され (EntityState.Added
)、そのValidFrom
値が現在の日付と時刻に設定されます。 - 元の変更されたエントリをデータベース値にリセットし (
.Reset()
エンティティを呼び出して)、ValidTo
その「古い」レコードを現在の日付と時刻に設定します。
次のように、オーバーライドで変更されたITemporalData
オブジェクトを簡単に除外できます。SaveChanges()
public partial class MyDbContext
{
// override the "SaveChanges" method
public override int SaveChanges()
{
DateTime currentDateTime = DateTime.Now;
// get the modified entities that implement the ITemporalData interface
IEnumerable<DbEntityEntry<ITemporalData>> temporalEntities = ChangeTracker.Entries<ITemporalData>().Where(e => e.State == EntityState.Modified);
foreach (var temporalEntity in temporalEntities)
{
// how would I do that, really? I only have an interface - can't clone an interface......
var cloned = temporalEntity.Entity.Clone();
// and once it's cloned, I would need to add the new record to the correct DbSet<T> to store it
// set the "old" records "ValidTo" property to the current date&time
temporalEntity.Entity.ValidTo = currentDateTime;
}
return base.SaveChanges();
}
}
「変更されたレコードのクローンを作成する」アプローチに苦労しています-実際にはインターフェースしかありません-しかし、クローン作成(AutoMapperまたは他のアプローチを使用)は常に実際の基礎となる具体的なデータ型にITemporalData
依存します.....