我正在尝试使用实体框架6.0和数据库第一种方法来实现继承。我想实现继承的原因是因为我想在我的所有表中添加以下字段。
它们是:( 实际上在通用数据库设计中,我们总是添加这些审核字段。)
我知道 TPT (每个类型的表格)是制作它的方法之一。但我不认为 TPT 是解决问题的正确方法。因为TPT需要为Base类型创建一个表。但就我而言,我认为没有必要。有什么方法可以做到吗?感谢。
答案 0 :(得分:7)
我建议数据库继承/ TPT / TPH对于这种情况不是必需的。你需要的只是一个img
界面:
IAuditable
然后你有两个选择:
如果您确定所有实体都是public interface IAuditable
{
string CreatedBy { get; set; }
DateTimeOffset CreatedTime { get; set; }
string ModifiedBy { get; set; }
DateTimeOffset? ModifiedTime { get; set; }
}
,则只需更改T4模板,以便所有自动生成的实体都能实现IAuditable
。
如果只有部分的实体为IAuditable
,您可以将部分类添加到可审核的实体中,例如:
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
以提供创建/修改实体的用户名。