我有一个基类
public class BaseClass
{
public int Id {get; set;}
}
和两个派生类
public class Foobar: BaseClass
{
[Required]
public int Whatever {get; set;}
}
public class Snafu: BaseClass
{
[Required]
public int Whatever {get; set;}
}
我使用表,每个层级继承和试图削减对我重复列,所以用流利的API我已经映射他们就像这样:
modelBuilder.Entity<Foobar>().Property(fb => fb.Whatever).HasColumnName("Whatever");
modelBuilder.Entity<Snafu>().Property(sf => sf.Whatever).HasColumnName("Whatever");
然而,这导致
(137,10):错误3023:问题在映射片段起始于线137:在表列的BaseClass BaseClass.Whatever必须映射:它没有缺省值和不可为空。
在EF6这种类型的映射似乎如果我脱下做工精细[Required]
从两个子类属性。 添加[DefaultValue(0)]
属性两者派生类不能解决问题。
任何想法如何获取这些属性在数据库共享列,同时保持其所需的属性?
这实际上是在EF6的错误。 在EF5的场景中使用不是在所有的工作(我们将抛出一个例外的线条“列名必须是唯一的”)。 虽然在EF6我们做了一些工作,以启用它,但显然我们错过了共享的列必须是,即使在派生类型,需要财产数据库可为空的事实。 后者是因为,除非基类是抽象的,你需要能够存储基本类型和基本类型的列应该是空的任何实例的实例。
我已经申请在我们的bug数据库的问题:
https://entityframework.codeplex.com/workitem/1924
随意选它。
至于解决方法,如果有中间人类型不是一个选项,您可以标记该列可为空明确附加实体上的配置,以.IsOptional()的调用。 这不会给你你想要什么,因为EF数据验证)的流畅API的目的这个调用IsOptional(将覆盖[必需]数据注解。 然而,数据验证的其他口味,如MVC的验证仍然会履行的属性。
有迹象表明,我没有尝试过其他可能的解决方法,也许,如果它是可以接受的使用TPT和既有派生类型都不管生活在一个不同的表,这将正常工作。 我相信,依靠设置默认值的任何做法将无助,因为错误不仅是不能够保持基类的一个实例,表架构,它也是有关的Code First不是生成的EF映射有效。
更新:此问题将在实体框架版本6.1.0这是目前测试版。
引入另一种类型,它包含其他两个共享所需的属性来完成你在找什么。 实体再看看这个:
public class BaseClass
{
public int Id { get; set; }
}
public abstract class BaseIntermediaryClass : BaseClass
{
[Required]
public int Whatever { get; set; }
}
public class Foobar : BaseIntermediaryClass
{
}
public class Snafu : BaseIntermediaryClass
{
}
而映射是这样的:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BaseIntermediaryClass>().Property(fb => fb.Whatever).HasColumnName("Whatever");
base.OnModelCreating(modelBuilder);
}
工作示例的完整代码可以在这里找到: https://gist.github.com/trayburn/7923392
文章来源: Reusing a column for a required property with Entity Framework 6.0, Fluent API, and DataAnnotations