2017-01-23 2 views
0

Ich habe zuerst ein Problem mit dem Vererbung-Code. Ich habe Basisklasse, die wie folgt aussehen:EF: Map-Basisklasse-Eigenschaft mit fließenden API

public abstract class BaseEntity 
{ 
    public DateTime? DateCreated { get; set; } 
    public string UserCreatedId { get; set; } 
    public DateTime? DateModified { get; set; } 
    public string UserModifiedId { get; set; } 
    public virtual UserState UserCreated { get; set; } 
    public virtual UserState UserModified { get; set; } 
} 

und ich habe Vererbung es und diese geben Sie mir eine zusätzliche Spalte mit dem Namen UserCreated_userStateId und UserModified_UserStateId. Also versuche ich fließend API wie folgt aus:

modelBuilder.Entity<BaseEntity>().HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId); 
modelBuilder.Entity<BaseEntity>().HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId); 

Aber geben Sie mir Fehler: „Ein oder mehrere Validierungsfehler während der Modellerzeugung erfasst wurden:

BaseEntity:. EntityType‚BaseEntity‘definiert hat keinen Schlüssel definieren der Schlüssel für diesen EntityType BaseEntities: EntityType: EntitySet 'BaseEntities' basiert auf dem Typ 'BaseEntity', der keine Schlüssel definiert hat. " Wie zu vermeiden, definieren Sie den Schlüssel und ändern Sie nur die Zuordnung der Eigenschaft? Ich habe Schlüssel in der abgeleiteten Klasse.

+0

Sie möchten also einzelne Schlüssel für jede abgeleitete Klasse definieren und die Strategie "Tabelle pro konkrete Klasse" verwenden? Dann sollten Sie die Basisklasseneigenschaften für abgeleitete Klassenentitäten konfigurieren. – grek40

+0

Wenn ich richtig verstehe, verwenden Sie nicht ** EF-Vererbung **, sondern einfache C# -Klassenvererbung? –

+0

Ja, aber ich habe zu viele abgeleitete Klasse, um alle eins nach dem anderen zu konfigurieren. Dies wird mir viele Copy Paste Code produzieren und ich will es nicht. Ist es eine bessere Lösung? Ja, ich habe C# -Klasse Vererbung Ich versuche, sauberes Modell zu bekommen und alles in flüssiger API zu bekommen. – CrazyBaran

Antwort

1

Sie können Ihre Basisklassenkonfiguration in eine generische Methode umbrechen und sie für jeden konkreten Entitätstyp aufrufen.

static void ConfigureBaseEntity<TDerived>(EntityTypeConfiguration<TDerived> entityTypeConfiguration) where TDerived : BaseEntity 
{ 
    // your base class configuration 
    entityTypeConfiguration.HasOptional(x => x.UserCreated).WithMany().HasForeignKey(x => x.UserCreatedId); 
    entityTypeConfiguration.HasOptional(X => X.UserModified).WithMany().HasForeignKey(x => x.UserModifiedId); 
} 

Anruf für jeden konkreten Entitätstyp

public class DerivedEntity : BaseEntity 
{ 
    public int Id { get; set; } 
} 

//... 
ConfigureBaseEntity(modelBuilder.Entity<DerivedEntity>()); 

bearbeiten

Vielleicht ist die Types Konfiguration ist für Ihre Zwecke ausreichend.

modelBuilder.Types<BaseEntity>().Configure(entityTypeConfiguration => /* configure using entityTypeConfiguration */); 

Andernfalls, wie kommentiert, benötigen Sie möglicherweise Reflexion. Nehmen wir beispielsweise an, alle abgeleiteten Klassen befinden sich in derselben Baugruppe wie die Klasse BaseEntity, und die Methode ConfigureBaseEntity von oben befindet sich in der Klasse BaseEntityConfiguration.

var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); 
var configurationMethod = typeof(BaseEntityConfiguration).GetMethod("ConfigureBaseEntity"); 
foreach (Type t in typeof(BaseEntity).Assembly.GetTypes().Where(x => x.IsSubclassOf(typeof(BaseEntity)))) 
{ 
    var configurator = entityMethod.MakeGenericMethod(t).Invoke(modelBuilder, new object[0]); 
    configurationMethod.MakeGenericMethod(t).Invoke(null, new object[1] { configurator }); 
} 

Allerdings, wenn es mein Code ist, würde ich es vorziehen, eine Zeile Code pro Entity-Klasse zu schreiben, anstatt für die dynamische Entdeckung gehen.

+0

Diese Antwort produzieren so viele kopieren einfügen Code, wenn ich viele DerivedEntity, vielleicht ist ein sauberer Weg, das zu tun? – CrazyBaran

+0

@CrazyBaran Fühlen Sie sich frei, Dinge wie Reflektion oder MEF zu verwenden, um eine abgeleitete Klassensammlung zu sammeln und eine reflexionsbasierte Version meines Codes zu erstellen, wenn ein Einzeiler pro konkreter Klasse zu viel für Ihren Fall ist. – grek40

+0

@CrazyBaran Siehe meine Bearbeitung, vielleicht ist das, was Sie brauchen – grek40

Verwandte Themen