实体框架5 - 基于枚举的派生类的判别器

Ale*_*lex 10 c# .net-4.0 ef-code-first entity-framework-5

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

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

我在我的DbContext中试过这个:

public class MyDbContext : DbContext
{
    DbSet<MyBaseClass> MyBaseClass { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MyBaseClass>()
                    .Map<DerivedOne>(m => m.Requires(x => x.MyEnum == MyEnum.Value1));

        base.OnModelCreating(modelBuilder);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,这会抛出以下InvalidOperationException:

表达式'x =>(Convert(x.MyEnum)== 0)'不是有效的属性表达式.表达式应该代表一个属性(...)

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

modelBuilder.Entity<MyBaseClass>().Map<DerivedOne>(m => m.Requires("MyEnum")
                                  .HasValue((Int32)MyEnum.Value1));
Run Code Online (Sandbox Code Playgroud)

现在我得到这个EntityCommandCompilationException:

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

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

Jon*_*mos 13

从 EF Core 开始,您可以通过Fluent API直接使用Enum。如果您的MyBaseClass未映射(是一个抽象类),您可以删除描述基本鉴别器的第一行HasValue行。在您的ApplicationDbContext中尝试以下代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<MyBaseClass>()
        .HasDiscriminator<MyEnum>("MyEnum")
        .HasValue<MyBaseClass>(MyEnum.Value0)
        .HasValue<DerivedOne>(MyEnum.Value1)
        .HasValue<DerivedTwo>(MyEnum.Value2);
}
Run Code Online (Sandbox Code Playgroud)


NSG*_*aga 7

据我所知,你不能这样做.明确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; } }
}
Run Code Online (Sandbox Code Playgroud)

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

if (entity is MyBaseClass) // instead of enum  
Run Code Online (Sandbox Code Playgroud)

或查询...

.OfType<MyBaseClass>();
Run Code Online (Sandbox Code Playgroud)