我有一堆实体实现了一个名为 ICreatableEntity
的接口(interface)。定义是:
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 配置中将其更改为可选,这也可以正常编译,但在插入我的种子数据时再次崩溃,因为我仍然将其有效保留为空。
是否有解决方法不需要我翻转逻辑并使其对所有内容都可为空,然后添加数十个 Fluent API 配置来告诉 EF 它实际上在其他任何地方都需要?
更新:只是为了提供更多信息,EF 每次都会重新生成数据库,因为我没有使用任何预先存在的东西。
最佳答案
我找到了一个我非常满意的解决方案。我突然想到,在指定外键时,我可以将 HasForeignKey()
或 Map()
与 Fluent API 一起使用。 HasForeignKey()
要求您在实体上指定一个已经存在的属性,但是 Map()
允许您指定 EF 将为您生成的属性名称作为外部属性 key 。由于在使用任何一种方法之前,关系已经配置为必需或可选(HasRequired()
、HasOptional()
),因此将考虑可空性。
所以,我只是这样做了,并从我的接口(interface)中删除了显式属性声明,这自动神奇地解决了我遇到的整个问题。这也有助于我开始使用一个基本配置类,它为实现我的接口(interface)的实体做了很多繁重的工作。我只需要为 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"));
}
}
我希望这对以后的人有帮助。
关于c# - Entity Framework 6.1 和使用新关键字隐藏成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23206559/