如何为泛型BaseEntity<TKey>在SaveChangesAsync中自动赋值CreatedAt和UpdatedAt
解决方案
针对泛型BaseEntity<TKey>无法直接做类型判断的问题,有两种常用的实现方案,优先推荐第一种类型安全的方案:
方案1:新增非泛型时间戳接口(推荐)
通过增加不含泛型参数的接口抽离时间戳属性,规避泛型类型判断的问题,无性能损耗,类型安全。
步骤1:定义非泛型接口
public interface IHasTimestamps { DateTime CreatedAt { get; set; } DateTime UpdatedAt { get; set; } }
步骤2:让泛型基类实现该接口
public abstract class BaseEntity<TKey> : IHasTimestamps { public TKey Id { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } }
步骤3:修改SaveChangesAsync中的逻辑
var entries = ChangeTracker .Entries() .Where(e => e.Entity is IHasTimestamps && ( e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entityEntry in entries) { var timestampEntity = (IHasTimestamps)entityEntry.Entity; // 如需UTC时间可替换为 DateTime.UtcNow timestampEntity.UpdatedAt = DateTime.Now; if (entityEntry.State == EntityState.Added) { timestampEntity.CreatedAt = DateTime.Now; } }
方案2:直接判断泛型基类(无需修改实体定义)
如果不想改动现有基类结构,可以通过反射判断实体是否继承自开放泛型类型BaseEntity<>,结合dynamic赋值即可:
var entries = ChangeTracker .Entries() .Where(e => // 递归判断实体是否继承自BaseEntity<>,如果继承层级深可单独封装为扩展方法 CheckIsSubclassOfOpenGeneric(e.Entity.GetType(), typeof(BaseEntity<>)) && (e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entityEntry in entries) { dynamic entity = entityEntry.Entity; entity.UpdatedAt = DateTime.Now; if (entityEntry.State == EntityState.Added) { entity.CreatedAt = DateTime.Now; } } // 泛型类型判断辅助方法 private static bool CheckIsSubclassOfOpenGeneric(Type type, Type openGenericType) { while (type != null && type != typeof(object)) { var currentType = type.IsGenericType ? type.GetGenericTypeDefinition() : type; if (openGenericType == currentType) { return true; } type = type.BaseType; } return false; }
内容的提问来源于stack exchange,提问作者Kay Ace Elits
相关产品推荐
相关产品推荐

