2013-04-07 9 views
8

Ich habe die folgenden (abgekürzt für die Klarheit) - eine Enum, eine Basisklasse mit dieser Enumeration, und zwei abgeleitete Klassen, die die Enumeration auf einen bestimmten Wert setzen.Entity Framework 5 - Enum basierte Diskriminator für abgeleitete Klassen

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; } 
} 

Was ich tun möchte, ist 5 Entity Framework automatisch unterscheiden zwischen DerivedOne und DerivedTwo, mit einem MyEnum Wert basiert Scheidungs ​​. Ich sollte in der Lage sein, dies zu tun, weil MyEnum == MyEnum.Value1 für DerivedOne steht und MyEnum == MyEnum.Value2 für DerivedTwo steht.

Ich habe versucht, dies in meinem 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); 
    } 
} 

Dies ist jedoch die folgende InvalidOperationException wirft:

Der Ausdruck 'x => (Rechnen (x.MyEnum) == 0)' nicht ist ein gültiger Eigenschaftsausdruck Der Ausdruck sollte eine Eigenschaft darstellen (...)

Edit: Ich glaube, ich habe ein wenig weiter dies mit:

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

Jetzt erhalte ich diese EntityCommandCompilationException:

Problem in Mapping-Fragmenten ab Zeile (...) Bedingung member 'MyBaseClass.MyEnum' mit einer anderen Bedingung als 'IsNull = False' ist zugeordnet. Entfernen Sie die Bedingung in MyBaseClass.MyEnum, oder entfernen Sie sie aus dem Mapping.

Irgendwelche Hinweise, wie ich das lösen kann? Vielen Dank!

Antwort

6

Soweit ich weiß, können Sie das nicht tun. Wenn Sie den Disciminator explizit Requires angeben, geben Sie ihm nur name - um ihn nicht mit Ihrer Eigenschaft zu verbinden.

Soweit ich weiß, führt das immer zu dem Fehler (später), den Sie beschreiben. Wenn Sie einen Diskriminator angeben wollen, muss er 'automatisch' sein (zumindest habe ich es nie so definiert).

Aber Sie brauchen das wirklich nicht. Der 'enum' und Diskriminator ist der Typ, den Sie zurückbekommen - basierend auf den Diskriminatorwerten konstruiert EF/CF entweder 'Base' oder 'DerivedOne' oder DerivedTwo.

So implementieren, was Sie möchten, dass Sie Folgendes tun können ...

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; } } 
} 

Oder is nur stattdessen verwenden (wenn es für Sie arbeitet) ...

if (entity is MyBaseClass) // instead of enum 

oder Query by ...

.OfType<MyBaseClass>(); 
3

Ab EF 6.1, ich war tatsächlich in der Lage eine ENUM als Diskriminator Spalte zu verwenden, trotz dieses Fehlers:

Additional information: Values of type 'MyEnum' cannot be used as type discriminator values. Supported types include byte, signed byte, bool, int16, int32, int64, and string.

Alles, was ich war, so etwas zu tun:

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> MyBaseClass { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations 
      .Add(new DerivedOneConfiguration()) 
      .Add(new DerivedTwoConfiguration()); 
    } 
} 

public class DerivedOneConfiguration : EntityTypeConfiguration<DerivedOne> 
{ 
    public DerivedOneConfiguration() 
    { 
     Map<DerivedOne>(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value1).IsRequired()); 
    } 
} 

public class DerivedTwoConfiguration : EntityTypeConfiguration<DerivedTwo> 
{ 
    public DerivedTwoConfiguration() 
    { 
     Map<DerivedTwo>(_ => _.Requires("MyEnum").HasValue((int)MyEnum.Value2).IsRequired()); 
    } 
} 

Also das Geheimnis mit (int)MyEnum.Value* statt MyEnum.Value* ...

1

Basierend auf der Antwort von @ Arsena, aber mit Zuordnung auf Basis von Microsofts Fluent Api Original-Dokumentation aktualisiert.

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> MyBaseClass { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Entity<MyBaseClass>() 
      .Map<DerivedOne>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value1)) 
      .Map<DerivedTwo>(x => x.Requires("MyEnum").HasValue((int)MyEnum.Value2)); 
    } 
}