entity framework5 – 基于枚举的派生类的判别器

我有以下内容(为了清楚起见,缩写) – 一个枚举,一个带有该枚举的基类,以及两个将枚举设置为特定值的派生类。

public enum MyEnum { Value1, Value2 } public class MyBaseClass { public MyEnum { get; protected set; } } public class DerivedOne: MyBaseClass { public DerivedOne { MyEnum = MyEnum.Value1; } } public class DerivedTwo: MyBaseClass { public DerivedTwo { MyEnum = MyEnum.Value2; } } 

我想要做的是让Entity Framework 5自动区分DerivedOne和DerivedTwo, 并使用基于MyEnum值的鉴别器 。 我应该能够这样做,按照惯例,每个MyEnum == MyEnum.Value1代表DerivedOne,而MyEnum == MyEnum.Value2代表DerivedTwo。

我在我的DbContext中试过这个:

 public class MyDbContext : DbContext { DbSet MyBaseClass { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity() .Map(m => m.Requires(x => x.MyEnum == MyEnum.Value1)); base.OnModelCreating(modelBuilder); } } 

但是,这会抛出以下InvalidOperationException:

表达式’x =>(Convert(x.MyEnum)== 0)’不是有效的属性表达式。 表达式应代表属性(…)

编辑:我相信我使用它更进一步:

 modelBuilder.Entity().Map(m => m.Requires("MyEnum") .HasValue((Int32)MyEnum.Value1)); 

现在我得到这个EntityCommandCompilationException:

从行开始映射片段的问题(…)映射条件成员’MyBaseClass.MyEnum’,其条件不是’IsNull = False’。 删除MyBaseClass.MyEnum上的条件或从映射中删除它。

关于如何解决这个问题的任何提示? 谢谢!

据我所知你不能这样做。 做明确的Requires指定说明者只是给它一个name – 而不是将它连接到你的财产。

据我所知,总是导致你所描述的错误(后来)。 如果你想指定鉴别器,它必须是’自动’的(至少我从未设法定义它)

但你真的不需要那样做 。 ‘enum’和鉴别器built into在你得到的类型中 – 根据鉴别器值,EF / CF构建’Base`或’DerivedOne’或DerivedTwo。

所以要实现你想要的,你可以做以下事情……

 public class MyBaseClass { [NotMapped()] public virtual MyEnum MyEnum { get { return MyEnum.Base; } } } public class DerivedOne: MyBaseClass { public string OneProp { get; set; } public override MyEnum MyEnum { get { return MyEnum.One; } } } public class DerivedTwo: MyBaseClass { public string TwoProp { get; set; } public override MyEnum MyEnum { get { return MyEnum.Two; } } } 

或者只是使用is (如果它适合你)…

 if (entity is MyBaseClass) // instead of enum 

或查询…

 .OfType(); 

从EF 6.1开始,我实际上能够使用枚举作为鉴别器列,尽管存在以下错误:

附加信息:“MyEnum”类型的值不能用作类型鉴别器值。 支持的类型包括byte,signed byte,bool,int16,int32,int64和string。

我所要做的就是这样:

 public enum MyEnum { Value1, Value2 } public class MyBaseClass { public MyEnum { get; protected set; } } public class DerivedOne: MyBaseClass { public DerivedOne() { MyEnum = MyEnum.Value1; } } public class DerivedTwo: MyBaseClass { public DerivedTwo() { MyEnum = MyEnum.Value2; } } public class MyDbContext : DbContext { DbSet MyBaseClass { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations .Add(new DerivedOneConfiguration()) .Add(new DerivedTwoConfiguration()); } } public class DerivedOneConfiguration : EntityTypeConfiguration { public DerivedOneConfiguration() { Map(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value1).IsRequired()); } } public class DerivedTwoConfiguration : EntityTypeConfiguration { public DerivedTwoConfiguration() { Map(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value2).IsRequired()); } } 

所以秘密是使用(int)MyEnum.Value*而不是MyEnum.Value*

基于@rsenna的答案,但更新了基于Microsofts Fluent Api原始文档的映射。

https://msdn.microsoft.com/en-us/library/jj591617%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396

 public enum MyEnum { Value1, Value2 } public class MyBaseClass { [NotMapped] public MyEnum MyEnum { get; protected set; } } public class DerivedOne: MyBaseClass { public DerivedOne() { MyEnum = MyEnum.Value1; } } public class DerivedTwo: MyBaseClass { public DerivedTwo() { MyEnum = MyEnum.Value2; } } public class MyDbContext : DbContext { DbSet MyBaseClass { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .Map(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value1)) .Map(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value2)); } }