数据库首先,如何在EF6中实现继承

Joe*_*ang 1 inheritance entity-framework entity-framework-6

我正在尝试使用实体框架6.0和数据库第一种方法实现继承.我想实现继承的原因是因为我想在我的所有表中添加以下字段.

它们是:( 实际上在常见的数据库设计中,我们总是添加这些审计字段.)

  • 由...制作
  • CreatedTime
  • ModyfiedBy
  • ModyfiedTime

我知道TPT(每种类型的表格)是制作它的方法之一.但我认为TPT不是解决问题的正确方法.因为TPT需要为Base类型创建一个表.但就我而言,我认为没有必要.有什么方法可以做到吗?谢谢.

rex*_*ghk 7

我建议数据库继承/ TPT/TPH对于这种情况不是必需的.你需要的只是一个IAuditable界面:

public interface IAuditable
{
    string CreatedBy { get; set; }

    DateTimeOffset CreatedTime { get; set; }

    string ModifiedBy { get; set; }

    DateTimeOffset? ModifiedTime { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

那你有两个选择:

  1. 如果您确定所有实体都是IAuditable,那么您只需更改T4模板,以便实现所有自动生成的实体IAuditable.

  2. 如果只有部分实体IAuditable,则可以将部分类添加到可审计实体,例如:

    public partial class Foo
    {
        // Auto-generated properties by EF
        public int Id { get; set; }
        ...
    } 
    
    Run Code Online (Sandbox Code Playgroud)

    然后在另一个文件中:

    public partial class Foo : IAuditable
    {
        // No implementation because auditable fields already exists
    }
    
    Run Code Online (Sandbox Code Playgroud)

然后,您可以从中派生抽象类DbContext以自动更新这些IAuditable属性:

public abstract class AuditableDbContext : DbContext
{
    public override int SaveChanges()
    {
        UpdateAuditableProperties();
        return base.SaveChanges();
    }

    public override async Task<int> SaveChangesAsync()
    {
        UpdateAuditableProperties();
        return await base.SaveChangesAsync();
    }

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
    {
        UpdateAuditableProperties();
        return await base.SaveChangesAsync(cancellationToken);
    }

    protected virtual void UpdateAuditableProperties()
    {
        var now = DateTimeOffset.Now;
        var userName = GetUserName();
        var changedAuditableEntities = from entry in ChangeTracker.Entries<IAuditable>()
                                       let state = entry.State
                                       where
                                           state.HasFlag(EntityState.Added) ||
                                           state.HasFlag(EntityState.Modified)
                                       select entry;

        foreach (var auditable in changedAuditableEntities)
        {
            var entity = auditable.Entry;

            switch (auditable.State)
            {
                case EntityState.Added:
                    entity.CreatedDate = now;
                    entity.CreatedBy = userName;
                    break;
                case EntityState.Modified:
                    entity.ModifiedDate = now;
                    entity.ModifiedBy = userName;
                    break;
            }
        }
    }

    protected abstract string GetUserName();
}
Run Code Online (Sandbox Code Playgroud)

DbContext可以从中派生AuditableDbContext,然后实现GetUserName()提供创建/修改实体的用户名.