之情况:
<button type="button">
问题是,每次创建表时我都要重复添加这两列。
但我想这样 -
<form>
但是在为部门或患者创建行时,它的创建问题[显示与其他表的外键冲突错误]。
在EF核心中,有每个层次结构表(TPH),但在这种情况下,每个表将合并到一个表中。但这并没有给我任何解决方案。
期待专家的建议......
答案 0 :(得分:3)
底线是:使用EntryLog
作为基本类型,不要告诉EF它。保持EF-core不遗漏基类型很容易:只注册派生类型。这样做,EF-core会将您的子类型映射到他们自己的表中,就好像它们没有共同类型一样。
现在EntryLog
将不再需要Id
,它应该是抽象的:
public abstract class EntryLog
{
public DateTime CreatedOnUtc { get; set; }
public string CreatedBy { get; set; }
}
这是否足够取决于您的具体要求。有几种可能性。
如果您对默认约定感到满意,EF将适用于公共属性,您已完成。 CreatedOnUtc
将映射到DateTime2
列(在Sql Server中)和CreatedBy
到nvarchar(max)
实体的每个表中的EntryLog
列。
但是,如果您确实需要自定义配置 - 例如,如果您想将CreatedBy
映射到nvarchar(50)
列,则应该应用其他映射说明。当然,您仍然只想对公共属性进行一次映射 - 如果 映射TPH方案中的基类型,也会发生这种情况。怎么做?
最简单的选择是添加数据注释:
public abstract class EntryLog
{
public DateTime CreatedOnUtc { get; set; }
[MaxLength(50)]
public string CreatedBy { get; set; }
}
就是这样。
但是有些开发团队不想使用数据注释来映射指令。此外,EF的流畅映射提供了比数据注释更多的选项。如果数据注释因任何原因而无法满足要求,则必须应用流畅的配置。但是,您仍然只想配置一次公共属性。实现这一目标的可行方法是为每个EntryLog
使用IEntityTypeConfiguration
,并让每个具体配置派生自基类。这提供了两个选项。
选项4将清楚说明为什么我在这里谈论“常规属性”。这就是它的样子:
abstract class EntryLogConfiguration
{
public void ConfigureBase<TEntity>(EntityTypeBuilder<TEntity> builder)
where TEntity : EntryLog
{
// Just an example of how to configure a base property.
builder.Property(e => e.CreatedBy).HasMaxLength(50);
}
}
class DepartmentConfiguration : EntryLogConfiguration,
IEntityTypeConfiguration<Department>
{
public void Configure(EntityTypeBuilder<Department> builder)
{
builder.Property(p => p.DepartmentName).HasMaxLength(100);
ConfigureBase(builder);
}
}
在上下文中:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new DepartmentConfiguration());
}
Shadow properties是EF-core的新功能。
影子属性是未在.NET实体类中定义但在EF Core模型中为该实体类型定义的属性。这些属性的值和状态完全保留在Change Tracker中。
假设您希望将CreatedBy
作为类属性(因为您希望在UI中显示它),但只需要CreatedOnUtc
作为在后台设置的属性,而不应该暴露。现在EntryLog
将如下所示:
public abstract class EntryLog
{
public string CreatedBy { get; set; }
}
所以属性CreatedOnUtc
消失了。它已作为shadow属性移动到基本配置:
abstract class EntryLogConfiguration
{
public void ConfigureBase<TEntity>(EntityTypeBuilder<TEntity> builder)
where TEntity : EntryLog
{
builder.Property(e => e.CreatedBy).HasMaxLength(50);
builder.Property<DateTime>("CreatedOnUtc");
}
}
现在,您无法直接设置CreatedOnUtc
,只能通过EF的更改跟踪器。最好的地方是在上下文中覆盖SaveChanges
:
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries<EntryLog>())
{
entry.Property<DateTime>("UpdatedOnUtc").CurrentValue = DateTime.UtcNow;
}
return base.SaveChanges();
}
当然,如果UpdatedOnUtc
是常规属性,这个覆盖也会派上用场,但你可以这样做
entry.Entity.CreatedOnUtc = DateTime.UtcNow;
我希望这会给你足够的思考,以找出最适合你的选择。