【问题标题】:Database first , How to implement inheritance in EF6数据库优先,如何在EF6中实现继承
【发布时间】:2015-08-11 01:43:17
【问题描述】:

我正在尝试使用实体框架 6.0 和数据库优先方法来实现继承。我想实现继承的原因是因为我想在我的所有表中添加这些字段。

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

  • 创建者
  • 创建时间
  • 修改者
  • 修改时间

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

【问题讨论】:

  • 请告诉我为什么不赞成我的问题。谢谢。

标签: entity-framework inheritance entity-framework-6


【解决方案1】:

我建议这种情况不需要数据库继承/TPT/TPH。你需要的只是一个IAuditable 接口:

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

    DateTimeOffset CreatedTime { get; set; }

    string ModifiedBy { get; set; }

    DateTimeOffset? ModifiedTime { get; set; }
}

那么你有两个选择:

  1. 如果您确定所有实体都是IAuditable,您可以简单地更改 T4 模板,以便所有自动生成的实体都将实现 IAuditable

  2. 如果您的实体中只有 一些IAuditable,您可以向这些可审计实体添加部分类,例如:

    public partial class Foo
    {
        // Auto-generated properties by EF
        public int Id { get; set; }
        ...
    } 
    

    然后在另一个文件中:

    public partial class Foo : IAuditable
    {
        // No implementation because auditable fields already exists
    }
    

然后您可以从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();
}

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

【讨论】:

  • :) 是的。对 。我只是在谷歌中搜索类似的东西。 (EF + 审计文件)。你的回答对我有很大帮助。谢谢。 +++1
  • 你能分享一些如何插入或更新实体的代码吗?特别是对于这些审计领域。谢谢。
  • 哇.. 非常好。但是,您有没有想过如何在 edmx 设计器中制作它?我的意思是,当 edmx 更新时,它可能需要更改从 IAuditable 继承的实体的生成代码。有没有可能这样做?谢谢。
  • 正如我在第一个选项中提到的,您可以更改生成实体的 T4 模板。通常它有一个.tt 的扩展名,它位于您的.edmx 文件旁边
  • 是的 .. 这应该是制作它的方法。我只是在实体框架6中测试了一下。.tt文件是代码生成模板文件。那就是它的工作原理。 :) 谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多