[EntityFramework] Optionale 1:1 beziehung

  • C#

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    [EntityFramework] Optionale 1:1 beziehung

    Hallo,

    ich arbeite seit kurzer Zeit mit dem EF und komm recht gut damit klar, aber nun stehe ich an meine Grenzen.
    Ich möchte eine optionale 1:1 beziehung zwischen zwei Entitäten herstellen.

    Es gibt die Klasse Drucksorte die jeweils verschiedene Vorlagen und Layouts besitzt. Außerdem hat jede Vorlage ein StandardLayout.
    Der Benutzer soll dann später zwischen StandardLayout und anderen Layouts dieser Drucksorte wählen können.

    C#-Quellcode

    1. public class Drucksorte
    2. {
    3. public int Id { get; set; }
    4. public string Bezeichnung { get; set; }
    5. public virtual ICollection<Vorlage> Vorlagen { get; set; }
    6. }
    7. public class Vorlage
    8. {
    9. public int Id { get; set; }
    10. public string Bezeichnung { get; set; }
    11. public virtual Drucksorte Drucksorte { get; set; }
    12. public Layout Layout { get; set; }
    13. }
    14. public class Layout
    15. {
    16. public int Id { get; set; }
    17. public string Bezeichnung { get; set; }
    18. public virtual Drucksorte Drucksorte { get; set; }
    19. public Vorlage Vorlage { get; set; }
    20. }


    Ich bekomme aber beim erstellen einer Migration folgende Fehlermeldung:

    Unable to determine the principal end of an association between the types 'fas.Entities.Layout' and 'fas.Entities.Vorlage'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.


    Mein Plan wäre, dass beim speichern einer neuen Vorlage anschließend ein Layout erstellt wird. Ob der FK bei Vorlagen oder bei Layouts steht ist nicht relevant.
    Hallo @windowsfan

    BITTE gebe immer an ob du mit EF <= 6 oder EF Core arbeitest. Da EF Core noch in Entwicklung ist bitte zusätzlich auch der genaue Version. Also z.b. aktuell die 2.1.1 angeben.
    Sonst müssen wir immer raten. Haben wir dich in deinen anderen Threads allerdings auch schon darauf aufmerksam gemacht. =O

    windowsfan schrieb:

    Es gibt die Klasse Drucksorte die jeweils verschiedene Vorlagen und Layouts besitzt. Außerdem hat jede Vorlage ein StandardLayout.

    Ne, die Klasse Drucksorte besitz viele Vorlagen aber keine Layouts. Vorlage besitz wiederum ein (1) Layout.

    windowsfan schrieb:

    Der Benutzer soll dann später zwischen StandardLayout und anderen Layouts dieser Drucksorte wählen können.

    OK, das regelst du aber über deine Logik. Hat jetzt mit der Struktur deines Models erstmal nicht viel zu tun.

    Bitte drücke dich klar auch und versuche Anhand von Beispielen zu Beschreiben was du erreichen willst. Ich denke (vieleicht liegt es aber auch an mir) das wir dir hier nicht ganz folgen können.

    Aber die Fehlermeldung sagt doch was du machen sollst. Du sollt über die Fluent API die verknüpfungen konfigurieren da diese art von Verknüpfung für die Logik von EF zu "hoch" ist.
    Das dies EF nicht selbst schafft kann natürlich auch daran liegen das du hier wie ich vermute wohl einen Denkfehler hast und eine gewisse Logik in dein Relationelles Datenmodell einfliessen lassen möchtest.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.
    Sorry, ich verwende EF6 und nicht EF Core

    Also der Benutzer kann Drucksorten anlegen. Dafür ist eigentlich nur eine Bezeichnung notwendig.

    Der Benutzer kann dann Layouts erstellen und diese Layouts einer Drucksorte zuordnen. Die Drucksorte wäre z.B. Visitenkarte und Layouts könnten z.B.
    "Visitenkarte Mittig", "Visitenkarte Rechtsbündig" sein.

    Außerdem kann der User Vorlagen erstellen. Dafür wählt er wieder eine Drucksorte aus zu der die Vorlage gehört, gibt eine Bezeichnung ein und wählt eine Vorlagen-Datei von seinem PC aus.
    Beim speichern dieser Vorlage wird außerdem ein Standard-Layout erstellt.

    Wenn der Benutzer eine Drucksorte (Visitenkarte), zwei Layouts ("Visitenkarte Mittig", "Visitenkarte Rechtsbündig") und eine Vorlage (z.B. Visitenkarte mit Blumen) erstellt hat, dann
    kann er diese in der "Drucken Maske" Ausählen.

    1. Wähle eine Drucksorte
    2. Wähle eine Vorlage

    C#-Quellcode

    1. db.Vorlagen.Where(x => x.Drucksorte.Id == selectedDrucksorte.Id).toList();

    Diese Vorlagen werden dann gefiltert in einer Combobox angezeigt.
    3. Wähle ein Layout -> 1. Item der Layout Combobox ist immer das Standard-Layout
    Der Rest sollte so oder ähnlich geladen werden

    C#-Quellcode

    1. db.Layouts.Where(x => x.Drucksorte.Id == selectedDrucksorte.Id).toList();


    Also das Layout sollte einen optionalen PrimaryKey haben und mit dem kann ich mir das Standard Layout einer Vorlage holen
    stelle ich mir so bzw. über LazyLoading vor (Egal wie ich es mache, es muss erstmal so in die Datenbank)

    C#-Quellcode

    1. db.Layouts.Where(x => x.Vorlage.Id == selectedVorlage.Id).FirstOrDefault();


    Hoffe es war einigermaßen verständlich!
    Hallo

    Wenn du das wirklich so haben möchtest kannst du das wie schon gesagt über die Fluent API konfigurieren. Du musst EF einfach beibringen wie Layout -> Vorlage und Layout -> Drucksorte verknüpft sind + jeweils die Verknüpfung retour zu Layouts.

    Ausserdem denke ich das dir (wenn ich keinen Denkfehler habe) eine Navigation zu Lyouts in Drucksorte fehlt oder?

    Hier mein kleiner Test!

    C#-Quellcode

    1. using System;
    2. using System.Collections.Generic;
    3. using System.Data.Entity;
    4. namespace EfTest
    5. {
    6. class Program
    7. {
    8. static void Main(string[] args)
    9. {
    10. using ( PrintContext db = new PrintContext())
    11. {
    12. var sorte1 = new Drucksorte() { Bezeichnung = "Testsorte" };
    13. var Layout1 = new Layout() { Bezeichnung = "Layout1", Drucksorte = sorte1 };
    14. sorte1.Vorlagen = new List<Vorlage>() { new Vorlage() { Bezeichnung = "Vorlage1", Drucksorte = sorte1, Layout = Layout1 } };
    15. db.Drucksorten.Add(sorte1);
    16. }
    17. Console.Read();
    18. }
    19. }
    20. public class PrintContext : DbContext
    21. {
    22. public DbSet<Drucksorte> Drucksorten { get; set; }
    23. public DbSet<Vorlage> Vorlagen { get; set; }
    24. public DbSet<Layout> Layouts { get; set; }
    25. protected override void OnModelCreating(DbModelBuilder modelBuilder)
    26. {
    27. base.OnModelCreating(modelBuilder);
    28. modelBuilder.Entity<Layout>().HasRequired(v => v.Vorlage).WithOptional(v1 => v1.Layout);
    29. modelBuilder.Entity<Layout>().HasRequired(v => v.Drucksorte).WithMany(v1 => v1.Layouts);
    30. }
    31. }
    32. public class Drucksorte
    33. {
    34. public int Id { get; set; }
    35. public string Bezeichnung { get; set; }
    36. public virtual ICollection<Vorlage> Vorlagen { get; set; }
    37. public virtual ICollection<Layout> Layouts { get; set; }
    38. }
    39. public class Vorlage
    40. {
    41. public int Id { get; set; }
    42. public string Bezeichnung { get; set; }
    43. public virtual Drucksorte Drucksorte { get; set; }
    44. public Layout Layout { get; set; }
    45. }
    46. public class Layout
    47. {
    48. public int Id { get; set; }
    49. public string Bezeichnung { get; set; }
    50. public virtual Drucksorte Drucksorte { get; set; }
    51. public Vorlage Vorlage { get; set; }
    52. }
    53. }


    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.