c# - 如何使用 Entity Framework 在保存的实体及其子属性上自动设置 CreatedOn 字段

标签 c# entity-framework inheritance entity-framework-6

每当我调用 databaseContext.SaveChanges() 时,在 Entity Framework 保存数据之前,我需要所有对象及其子类在 CreatedOn 字段中填充 DateTime.Now().

详细信息:我有一个所有实体都继承自的 BaseEntity 类:

 public class BaseEntity
 {
        [Key]
        public virtual Guid Id{ get; set; }
        public DateTime CreatedOn { get; set; }
 }

每当从上面的 BaseEntity 继承的实体被保存时,CreatedOn 属性就会被分配 DateTime.Now

这是一个基本存储库:

public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : BaseEntity
{
     ....

     public virtual bool SaveChanges(TEntity entity)
     {            
         if (entity.CreatedOn == DateTime.MinValue)
             entity.CreatedOn = DateTime.Now;
         else
             entity.ModifiedOn = DateTime.Now;

         return _databaseContext.SaveChanges() > 0;           
     }
}

这很好用,但问题是只有对象本身的 CreatedOn 属性得到更新。那里的任何子类都可能得到更新。

如何更改 SaveChanges() 方法中的逻辑以更新所有子类并设置它们的 CreatedOn 日期?

我将提供一个例子来说明这一点:想象一个 User 对象的实例被添加到 dbContext 中,并带有一个新的 Profile,以及分配新的 Role 类实例,然后调用 SaveChanges():

public class User: BaseEntity
{
        [Key]
        public virtual Guid Id { get; set; }

        public UserRole Role { get; set; }
        public ProfileDetails Profile { get; set; }
        public DateTime CreatedOn { get; set; }
        public Guid CreatedBy { get; set; }
}

什么是确保为子 user.Role 以及 user.Profile 对象分配 CreatedOn 日期的最佳方法(这两个类也都继承自 BaseEntity)?我考虑过使用反射来检查 CreatedOn 字段的子对象属性,但所有循环都感觉不对。有没有更好的办法?

最佳答案

基本上,您应该重写您自己的数据库上下文类中的 SaveChanges 方法并使用 EF 更改跟踪器获取所有新创建的对象,然后设置它们的 CreatedOn 字段因此。

大致是这样的:

public class DbContextBase : DbContext 
{
    public override int SaveChanges() 
    {
        DateTime currentDateTime = DateTime.Now;

        // get all the entities in the change tracker - this could be optimized
        // to fetch only the entities with "State == added" if that's the only 
        // case you want to handle
        IEnumerable<DbEntityEntry<BaseEntity>> entities = ChangeTracker.Entries<BaseEntity>();

        // handle newly added entities
        foreach (DbEntityEntry<BaseEntity> entity in entities.Where(e => (e.State == EntityState.Added)) 
        {
            // set the CreatedOn field to the current date&time
            entity.Entity.CreatedOn = currentDateTime;
        }

        // to the actual saving of the data
        return base.SaveChanges();
    }
}

当然你可以对此进行改进:

  • 还使用 e.State == EntityState.Modified 处理实体,并在这种情况下设置 ModifiedOn 字段
  • 添加一些自定义异常处理来处理常见问题
  • 还有更多 - 天空和您的想象力是无限的!

关于c# - 如何使用 Entity Framework 在保存的实体及其子属性上自动设置 CreatedOn 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60023544/

相关文章:

c# - 获取上次修改或创建文件的用户名

c# - 并行循环内的局部变量线程安全

c# - .Net 4.5 和 4.0 中 Async 方法的 Out 关键字替换是什么?

asp.net-mvc - 使用瘦 Controller 的 N 层域/ View 模型的最佳实践

c++ - 我可以使用在 CUDA 内核中实现纯虚函数的类吗?

c# - C# 计时器是否在单独的线程上流逝?

.net - Entity Framework 性能问题

visual-studio - EF Core 数据库优先的 "No executable found matching command dotnet-ef"错误

C++:模板化继承递归类:不可能的三重威胁?

python - 多重继承怪癖,还是 Python 中的 Bug?