首页 > 解决方案 > 初始化实体的通用属性

问题描述

我有许多实体模型,它们都有一些共同的属性,如下所示

  1. 创建于
  2. 创建者
  3. 上次修改时间
  4. 最后修改者

每次我需要将对象保存在数据库中时,我都必须手动初始化这些属性。我想要一个方法或一些基类,我可以在其中初始化这些属性,以避免一次又一次地编写相同代码的麻烦。注意:我想要没有基本构造函数的基类的通用实现。先感谢您

标签: c#.netinheritanceasp.net-core-2.0

解决方案


由于多种原因,您不能对实体类执行此操作。CreatedOn可以通过默认值来处理,但其余的需要实体类永远不会拥有的知识,例如HttpContext.User或仅仅是它是否正在被修改或创建。

相反,您需要将此功能构建到您的上下文中。首先,您应该让所有实体类都实现一个特定的接口,以便从特定的基类继承。在任何一种情况下,您都希望将这些属性添加到其中,以便您可以确保任何实现/派生类都将拥有所述属性。

然后,您可以向上下文类添加一个私有方法,例如:

private void PopulateAuditTrailProperties()
{
    var httpContextAccessor = this.GetService<IHttpContextAccessor>();
    var username = httpContextAccessor?.HttpContext.User.Identity.Name;

    foreach (var entry in ChangeTracker.Entries<IEntity>().Where(x => x.State == EntityState.Added))
    {
        entry.Entity.CreatedOn = DateTimeOffset.UtcNow;
        entry.Entity.CreatedBy = username;
    }

    foreach (var entry in ChangeTracker.Entries<IEntity>().Where(x => x.State == EntityState.Modified))
    {
         entry.Entity.ModifiedOn = DateTimeOffset.UtcNow;
         entry.Entity.ModifiedBy = username;
     }
}

然后,您需要在您的上下文中覆盖SaveChangesSaveChangesAsync让每个人在保存之前调用此方法:

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
    PopulateAuditTrailProperties();
    return base.SaveChanges(acceptAllChangesOnSuccess);
}

public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
    PopulateAuditTrailProperties();
    return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}

最后,你需要在你的Startup.cs:

services.AddDbContext<MyContext>(o =>
    o.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
        .UseInternalServiceProvider()); // Add this line

和:

services.AddHttpContextAccessor();

推荐阅读