我已经设置了一组从“基本”实体继承的实体,该实体包含键字段和2个日期时间审核字段:
/// <summary>
/// The <see cref="BaseEntity"/> class is a standard entity from which all other entities inherit.
/// </summary>
public abstract class BaseEntity
{
/// <summary>
/// Universal unique identifier for the entity.
/// </summary>
public Guid Guid { get; set; }
/// <summary>
/// Timestamp for when the entity was created.
/// </summary>
public DateTime CreatedAtTime { get; set; }
/// <summary>
/// Timestamp for when the entity was last updated.
/// </summary>
public DateTime UpdatedAtTime { get; set; }
}
我已经设置了一个继承此抽象类的实体:
/// <summary>
/// A <see cref="MilitaryUnit"/> is a group of <see cref="MilitaryMember"/>'s that work together
/// and have a 'chain of command'
/// </summary>
public class MilitaryUnit : BaseEntity
{
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<MilitaryMember> Members { get; set; }
public virtual ICollection<MilitaryUnitSection> Sections { get; set; }
public MilitaryUnit()
{
this.Members = new HashSet<MilitaryMember>();
this.Sections = new HashSet<MilitaryUnitSection>();
}
}
在我的DbContext中,我创建了一个引用'MilitaryUnit'实体的DbSet,并应用了配置:
DbContext
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options) { }
public DbSet<MilitaryUnit> MilitaryUnits { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration<MilitaryUnit>(new MilitaryUnitConfiguration());
}
军事单位配置
public class MilitaryUnitConfiguration : IEntityTypeConfiguration<MilitaryUnit>
{
public void Configure(EntityTypeBuilder<MilitaryUnit> builder)
{
// All entities inherit from the BaseEntity type
builder.HasBaseType<BaseEntity>();
// The unit name can only be 50 characters long and is unique
builder.Property(entity => entity.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
builder.HasAlternateKey(entity => entity.Name);
// The unit has a description that can be up to 100 character long
builder.Property(entity => entity.Description)
.HasColumnType("varchar(100)")
.HasMaxLength(100);
// The unit has multiple members
builder.HasMany<MilitaryMember>(entity => entity.Members);
// The unit has multiple sections
builder.HasMany<MilitaryUnitSection>(entity => entity.Sections);
}
}
当我尝试应用迁移时,出现以下错误:
无法在“ MilitaryUnit”上配置密钥,因为它是派生的 类型。该密钥必须在根类型“ BaseEntity”上进行配置。如果你 不打算将“ BaseEntity”包含在模型中,请确保 它不包含在您的上下文的DbSet属性中, 在对ModelBuilder的配置调用中引用,或从 模型中包含的类型上的导航属性。
现在,我具有“ BaseEntity”的模型配置:
public class BaseEntityConfiguration : IEntityTypeConfiguration<BaseEntity>
{
public void Configure(EntityTypeBuilder<BaseEntity> builder)
{
builder.HasKey(entity => entity.Guid);
builder.Property(entity => entity.Guid)
.HasColumnType("guid");
builder.Property(entity => entity.CreatedAtTime)
.HasColumnType("datetime")
.HasValueGenerator(typeof(CurrentDateTimeGenerator))
.ValueGeneratedOnAdd();
// The updated timestamp has a default value of the minimum date time value and will only
// generate a new date time when the entity has been updated
builder.Property(entity => entity.UpdatedAtTime)
.HasColumnType("datetime")
.HasDefaultValue(DateTime.MinValue)
.HasValueGenerator(typeof(CurrentDateTimeGenerator))
.ValueGeneratedOnUpdate();
}
}
...但是我不确定该在哪里应用!我以为它在DbContext中的某个位置,但是尝试了之后,仍然出现错误(如上所述)。我要疯了,完全看不见什么东西?
答案 0 :(得分:1)
感谢所有回复!因此,似乎解决方案并不太可怕:
我将BaseEntityConfiguration类设置为一个抽象类,该类采用我要配置的实体类型并实现IEntityTypeConfiguration接口,并使Configure方法能够“覆盖”。
BaseConfiguration
public abstract class BaseEntityConfiguration<TEntityType> : IEntityTypeConfiguration<TEntityType>
where TEntityType : BaseEntity
{
public virtual void Configure(EntityTypeBuilder<TEntityType> builder)
{
builder.HasKey(entity => entity.Guid);
// The created timestamp has a default value of the current system time for when the entity
// was created in the database. This value cannot be changed after it is set
builder.Property(entity => entity.CreatedAtTime)
.HasColumnType("datetime")
.HasValueGenerator(typeof(CurrentDateTimeGenerator))
.ValueGeneratedOnAdd();
// The updated timestamp has a default value of the minimum date time value and will only
// generate a new date time when the entity has been updated
builder.Property(entity => entity.UpdatedAtTime)
.HasColumnType("datetime")
.HasDefaultValue(DateTime.MinValue)
.HasValueGenerator(typeof(CurrentDateTimeGenerator))
.ValueGeneratedOnUpdate();
}
}
然后在实体配置类上,我扩展此BaseEntityConfiguration类并覆盖Configure方法,同时从抽象类执行基本的Configure方法:
public class MilitaryUnitConfiguration : BaseEntityConfiguration<MilitaryUnit>
{
public override void Configure(EntityTypeBuilder<MilitaryUnit> builder)
{
base.Configure(builder);
// The unit name can only be 50 characters long and is unique
builder.Property(entity => entity.Name)
.HasColumnType("varchar(50)")
.HasMaxLength(50)
.IsRequired();
builder.HasAlternateKey(entity => entity.Name);
// The unit has a description that can be up to 100 character long
builder.Property(entity => entity.Description)
.HasColumnType("varchar(100)")
.HasMaxLength(100);
// The unit has multiple members
builder.HasMany<MilitaryMember>(entity => entity.Members);
// The unit has multiple sections
builder.HasMany<MilitaryUnitSection>(entity => entity.Sections);
}
}
虽然我尚未对此进行彻底的测试,但似乎迁移已成功设置:
migrationBuilder.CreateTable(
name: "MilitaryUnits",
columns: table => new
{
Guid = table.Column<Guid>(nullable: false),
CreatedAtTime = table.Column<DateTime>(type: "datetime", nullable: false),
UpdatedAtTime = table.Column<DateTime>(type: "datetime", nullable: false, defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)),
Name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false),
Description = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_MilitaryUnits", x => x.Guid);
table.UniqueConstraint("AK_MilitaryUnits_Name", x => x.Name);
});