2016-07-05 16 views
2

ist ich eine Elternklasse ComponentDesign haben:Entity Framework eine Eins-zu-eins mit einer Klasse, die manchmal unabhängig

public class ComponentDesign 
{ 
    public string Name { get; set; } 

    public virtual JobFile DesignFile { get; set; } 
    public int? DesignFileId { get; set; } 

    public Pdf PdfFile { get; set; } 
    public int? PdfFileId { get; set; } 

    public JobFile SealedPdfFile { get; set; } 
    public int? SealedPdfFileId { get; set; } 

    public int Id { get; set; } 

    public int JobId { get; set; } 
} 

Und ein Kind Klasse JobFile (davon Pdf ist eine Unterklasse):

public class JobFile 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Url { get; set; } 

    public ComponentDesign ComponentDesign { get; set; } 
    public int? ComponentDesignId { get; set; } 

    public int? JobId { get; set; } 
} 

Diese Klassen werden mithilfe von Entity Framework in einer relationalen Datenbank gespeichert. Ich hätte gerne Navigationseigenschaften auf beiden Seiten der Beziehung, so dass ich nach Belieben componentDesign.PdfFile oder jobFile.ComponentDesign sagen kann.

Jede Eigenschaft des Typs JobFile in ComponentDesign ist optional, und ein JobFile will only ever belong to one ComponentDesign . However, a Job-Datei may be free-standing, not belonging to any ComponentDesign (so jobFile.ComponentDesign` wäre null).

Ich habe Probleme mit der Verwendung der Fluent-API, um diese Beziehung zu konfigurieren. Es ist eins zu eins. Ist es möglich, die Navigationseigenschaften auf beiden Seiten der Beziehung zu haben? Denken Sie daran, dass ein JobFile freistehend sein kann (so dass jobFile.ComponentDesign nicht immer relevant sein wird), so dass es JobFile s gibt, die zu ComponentDesign gehören und solche, die dies nicht tun. Das nächste, was ich fühle ich gekommen bin, ist dies:

modelBuilder.Entity<ComponentDesign>() 
      .HasOptional(componentDesign => componentDesign.DesignFile) 
      .WithRequired(jobFile => jobFile.ComponentDesign); 

Aber das scheint mir zu zeigen, dass jobFile.ComponentDesign ist immer dann erforderlich, was nicht der Fall ist. Ich zögere, es einfach zu versuchen, weil es einige wesentliche Migrationen erzeugt, also wollte ich zuerst eine Eingabe erhalten. Wie sollte meine Fluent API-Konfiguration für diese Situation aussehen? verstehen

+0

Um eine Beziehung in Entity Framework zwischen zwei Objektklassen oder, sagen wir, Datatabellen zu erstellen, können Sie das virtuelle Wort mit dem Klassentyp verwenden. Ich bin sicher, dass Sie Ergebnisse mit virtuellen Eigenschaften für Ihr Problem finden können. –

Antwort

2

einfach so, dass ich die Beziehungen:

ComponentDesign ->JobFile = Optional.

JobFile ->ComponentDesign = Optional.

Dies ist eine Null-oder-Eins-zu-Null-Beziehung ([0/1] - [0/1]).

Dies kann auf folgende Weise implementiert werden, mit der .WithOptionalPrincipal Methode in fließenden API. Bei einer 1-0 Beziehung ist es offensichtlich, welches Ende das Hauptende ist; Gleiches mit einer 1-∞-Beziehung. ∞-∞-Beziehungen haben kein Hauptende, da die ausgeblendeten Tabellen die Beziehungen zwischen den Beziehungen steuern. Bei einer 0/1-0/1- oder 1-1-Beziehung ist dies nicht offensichtlich und Sie müssen der Datenbank mitteilen, welches Ende als Hauptschluss der Beziehung verwendet werden soll. Neben vielen anderen Dingen ist das Prinzip verantwortlich für die Initiierung und Aufrechterhaltung der Beziehung zwischen den Tabellen.

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    // Configure ComponentDesign & JobFile entity 
    modelBuilder.Entity<ComponentDesign>() 

     // Mark JobFile property optional in ComponentDesign entity. 
     .HasOptional(cd => cd.DesignFile) 

     // Mark ComponentDesign property optional in JobFile entity. 
     .WithOptionalPrincipal(jf => jf.ComponentDesign); 
} 

Oder können Sie eine EntityTypeConfiguration<> Klasse erstellen für jede Entität, die die Beziehungen zu trennen, wenn es eine Menge zu sortieren sind. Während dies die Beziehungen dezentralisiert, ist es besser skalierbar, da diese Konfigurationsklassen über den MEF injiziert werden können, sobald der Kontext dafür konfiguriert ist. Nur eine Idee für die zukünftige Entwicklung.

Wenn Sie die Beziehung vom JobFile-Ende aus konfigurieren würden, würden Sie .WithOptionalDependent verwenden, um die Navigation korrekt zu setzen, anstatt .WithOptionalPrincipal. Alles hängt davon ab, auf welcher Seite Sie die Beziehung konfigurieren.Die ComponentDesign Einheit beruht auf der JobFile Einheit viel mehr als die JobFile Einheit beruht auf der ComponentDesign Einheit; Daher sollte es als Prinzipal konfiguriert werden. Wie in einem der obigen Kommentare angegeben, sollten komplexe Eigenschaften mit dem Schlüsselwort virtual versehen werden. Dieser Lazy lädt die Eigenschaft, und wenn die Klasse intansiated ist, legt es den Anfangswert auf null fest.

Klonen Sie die Datenbank auf einen Testserver, um an diesem einen Problem zu arbeiten, und implementieren Sie anschließend die Änderungen am Produktionsmodell. Auf diese Weise besteht keine Gefahr eines Datenverlusts bei der Migration der Datenbank.