【问题标题】:How to automatically set DateCreated and DateUpdated如何自动设置 DateCreated 和 DateUpdated
【发布时间】:2014-02-20 15:21:46
【问题描述】:

如果我有以下实体:

public class PocoWithDates {
    public string PocoName { get; set; }
    public DateTime DateCreated { get; set; }
   public DateTime DateUpdated { get; set; }
}

对应同名/属性的 SQL Server 2008 (R2) 表...

我怎样才能自动: - 在执行 INSERT 时将 DateCreated 和 DateUpdated 字段设置为现在 - 在进行更新时将DateUpdated 字段设置为现在

当我自动说的时候,我的意思是我希望能够做到这一点:

poco.Name = "Changing the name";
repository.Save(); 

不是这个:

poco.Name = "Changing the name";
poco.LastModified = DateTime.Now;
repository.Save();

在幕后,“某事”应该会自动更新 DateTime 字段。那“东西”是什么?我正在使用实体框架 6.0。 EF有没有办法自动做到这一点?我知道 MySQL 可以做这样的事情。或者在 SQL Server 中使用触发器/存储过程。但我不想那样。

这个问题是这个问题的替代和修改版本: Entity Framework/SQL2008 - How to Automatically Update LastModified fields for Entities?

这个问题为 EF 4.0 提供了一些很好的解决方案/答案。但我希望它用于带有DBContext 的 EF6.0。如果我有更多时间,我会尝试调整这些解决方案并让它们在 EF6.0 中运行。但现在我想知道是否有人已经解决了这个问题,或者知道如何将 EF4.0 的自定义 SaveChanges() 或 Add() 覆盖转录为 EF6.0。

【问题讨论】:

    标签: c# .net sql-server entity-framework entity-framework-6


    【解决方案1】:

    您可以覆盖 DbContext 上的 SaveChanges() 方法以更新 Save() 上的 DateUpdated 值。我会实现一个接口以允许更新某些项目而其他项目不更新。

    public interface IEntityAutoDateFields
    {
        DateTime DateCreated { get; set; }
        DateTime DateUpdated { get; set; }
    }
    

    然后:

    public class PocoWithDates : IEntityAutoDateFields
    {
        public PocoWithDates()
        {
    
        }
    
        public DateTime DateCreated { get; set; }
        public DateTime DateUpdated { get; set; }
    }
    

    在你的上下文中:

    public PocoWithDatesContext : DbContext
    {
         public DbSet<PocoWithDates> PocoWithDatesSet { get; set;}
    
         public override int SaveChanges()
         {
             var now = DateTime.Now;             
    
             this.ChangeTracker.DetectChanges();
             foreach (var item in this.ChangeTracker.Entries()
                                   .Where(i => i.State == EntityState.Added || i.State == EntityState.Modified)
                                   .Where(i => i as IEntityAutoDateFields != null))
             {
                 if (item.State == EntityState.Added)
                 {
                      (item as IEntityAutoDateFields).DateCreated = now;
                 }
                 (item as IEntityAutoDateFields).DateUpdated = now;
             }
             // Call the SaveChanges method on the context;
             return base.SaveChanges();
         }
    }
    

    【讨论】:

    • 太棒了!我会接受这个答案。现在我正在解决一些其他问题,然后才能进行全面测试。我确实将接口重命名为IEntityAutoDateFields,并在EntityState.Added 的SaveChanges 覆盖中添加了一个测试/列表,其中设置了DateCreated 和DateUpdated。我想在一个地方完成这两项工作,而不是需要为每个实现IEntityAutoDateFields 的新类实现一个构造函数。 @James-warne,您能否也更改答案中的这两件事,然后我会将您的答案标记为答案。否则我会在完成后根据你的答案添加我自己的答案。
    【解决方案2】:

    这是基于 Ben Cull solution。我刚刚添加了处理异步方法 SaveChangesAsync()。

    1 创建基类

    public class BaseEntity
    {
        public DateTime? DateCreated { get; set; }
        public string UserCreated { get; set; }
        public DateTime? DateModified { get; set; }
        public string UserModified { get; set; }
    }
    

    2 将 Base 应用到现有类

    public class Student : BaseEntity
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
    

    3 在 DBContext 类中覆盖 SaveOn() 和 SaveOnSync()

    public class SchoolContext : DbContext
    {
    
    public override int SaveChanges()
    {
        var entities = ChangeTracker.Entries().Where(x => x.Entity is BaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));
    
        var currentUsername = HttpContext.Current != null && HttpContext.Current.User != null
            ? HttpContext.Current.User.Identity.Name
            : "Anonymous";
    
        foreach (var entity in entities)
        {
            if (entity.State == EntityState.Added)
            {
                ((BaseEntity)entity.Entity).DateCreated = DateTime.Now;
                ((BaseEntity)entity.Entity).UserCreated = currentUsername;
            }
    
            ((BaseEntity)entity.Entity).DateModified = DateTime.Now;
            ((BaseEntity)entity.Entity).UserModified = currentUsername;
        }
    
        return base.SaveChanges();
    }
    }
    
    public override Task<int> SaveChangesAsync(System.Threading.CancellationToken cancellationToken)
    
        {
            var entities = ChangeTracker.Entries().Where(x => x.Entity is BaseEntity && (x.State == EntityState.Added || x.State == EntityState.Modified));
    
            var currentUsername = HttpContext.Current != null && HttpContext.Current.User != null
                ? HttpContext.Current.User.Identity.Name : "Anonymous";
    
    
            foreach (var entity in entities)
            {
                if (entity.State == EntityState.Added)
                {
                    ((BaseEntity)entity.Entity).DateCreated = DateTime.Now;
                    ((BaseEntity)entity.Entity).UserCreated = currentUsername;
                }
    
                ((BaseEntity)entity.Entity).DateModified = DateTime.Now;
                ((BaseEntity)entity.Entity).UserModified = currentUsername;
            }
    
            return base.SaveChangesAsync(cancellationToken);
        }
        }
    

    【讨论】:

      【解决方案3】:

      添加一个构造函数以在您的实体的新实例上设置 DateCreated/DateUpdated。

      public class PocoWithDates {
          public PocoWithDates()
          {
              this.DateCreated = DateTime.Now;
              this.DateUpdated = this.DateCreated;
          }
      
          public string PocoName { get; set; }
          public DateTime DateCreated { get; set; }
          public DateTime DateUpdated { get; set; }
      }
      

      至于自动修改 Save() 上的 DateUpdated,您可能希望查看 here。

      【讨论】:

        猜你喜欢
        • 2010-09-19
        • 1970-01-01
        • 2023-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-30
        相关资源
        最近更新 更多