我有一堆实体实现了一个名为ICreatableEntity
的接口。定义是:
public interface ICreatableEntity {
int CreatedById { get; set; }
Employee CreatedBy { get; set; }
DateTime CreatedDateTime { get; set; }
}
一个特定的实体Employee
需要稍加修改,因为第一个记录不能有创建者,因此我需要使列可以为空。所以,我只是尝试使用new关键字隐藏继承的成员,如:
public new int? CreatedById { get; set; }
一切正常,编译器喜欢它和所有,但是当模型由EF生成时,它会因为项目已存在于元数据集合中而崩溃。我猜,EF可能首先添加我的覆盖,然后继续添加基本属性,即使我试图隐藏它,那就是它崩溃的时候。
更新:我试图保持原样并在Fluent API配置中将其更改为Optional,它也编译得很好,但是当插入我的种子数据时再次崩溃,因为我仍然留下它实际上是空的。
是否有一个解决方法,不需要我翻转逻辑并使其可以为所有内容为空,然后添加几十个Fluent API配置来告诉EF它实际上是否需要其他地方?
更新:为了提供更多信息,每次EF都会重新生成数据库,因为我没有使用任何预先存在的内容。
答案 0 :(得分:0)
我找到了一个我非常满意的解决方案。我指出,在指定外键时,我可以使用Fluent API HasForeignKey()
或Map()
。 HasForeignKey()
要求您在实体上指定已存在的属性,但Map()
允许您指定EF将为您生成的属性的名称作为外键。由于在使用任一方法之前,关系已经被配置为必需或可选(HasRequired()
,HasOptional()
),因此可以考虑可为空性。
所以,我只是这样做,并从我的接口中删除了显式属性声明,这自动神奇地解决了我遇到的整个问题。这也有助于我开始使用基本配置类,它为实现我的接口的实体做了很多繁重的工作。我只需要为Employee
配置覆盖一次特定方法,就可以了。
这是一个缩短版本的基本配置类,使事情发生。
internal class Configuration<TEntity> :
EntityTypeConfiguration<TEntity>
where TEntity : class, ICreatableEntity, new() {
protected virtual void Configure() {
this.Configure(ConfigurationParameters.Default);
}
protected virtual void Configure(
ConfigurationParameters parameters) {
this.ConfigureCreatableRelationships(parameters.CreatedByWillCascadeOnDelete);
}
#region Relationship Configurations
protected virtual void ConfigureCreatableRelationships(
bool willCascadeOnDelete) {
this.HasRequired(
t =>
t.CreatedBy).WithMany().Map(
m =>
m.MapKey("CreatedById")).WillCascadeOnDelete(willCascadeOnDelete);
}
#endregion
}
我的EmployeeConfiguration
课程中的覆盖:
internal sealed class EmployeeConfiguration :
Configuration<Employee> {
protected override void ConfigureCreatableRelationships(
bool willCascadeOnDelete) {
this.HasOptional(
t =>
t.CreatedBy).WithMany().Map(
m =>
m.MapKey("CreatedById"));
}
}
我希望将来可以帮助某人。