Laden...

[EF Core 2.1] dritte Entity mit Bezug auf M:N Beziehung zweier anderer Tabellen erstellen

Erstellt von sronny vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.394 Views
S
sronny Themenstarter:in
6 Beiträge seit 2019
vor 5 Jahren
[EF Core 2.1] dritte Entity mit Bezug auf M:N Beziehung zweier anderer Tabellen erstellen

Ich wünsche erst einmal allen ein gesundes neues Jahr.

Habe immer mal wieder hier im Forum gestöbert und doch jetzt einmal eine Frage:

Ich verwende EF Core 2.1 und versuche folgendes zu erstellen:

Entity 1:



public class PersonTbl
{

public int Id {get;set}

public virtual ICollection<PersonAdressenTbl> PAdressenList{get;set;

}

Entity 2:



public class AdresseTbl
{

public int Id {get;set}

public virtual ICollection<PersonAdressenTbl> PAdressenList{get;set;}

}

M:N Beziehung PersonAdressen



public class PersonAdressenTbl
{

public int Id{get;set;}

public int PersonId{get;set}

public int AdresseId{get;set;}

public int PKAdresseID {get;set;}
public int PKAdresse {get;set;}


public virtual PersonTbl Person {get;set;}
public virtual AdresseTbl Adresse {get;set;}

public virtual ICollection<PersonKostentraegerTbl> PersonKostentraegerList{get;set;}

}

nun habe ich noch eine dritte M:N Tabelle mit Selbstbezug auf PersonTbl. Ob diese so funktioniert, weiß ich noch nicht, denn ich möchte in dieser eine Beziehung zu PersonAdresseTbl erstellen, doch das scheitert schon beim migrieren.



public class PersonKostentraegerTbl
{

public int Id{get;


public int KostentraegerAdresseId{get;set;}
public virtual PersonAdresseTbl KostentraegerAdresse{get;set;}

}

modelCreating:

modelbuilder.Entity<PersonKostentraegerTbl>()
.HasOn<PersonAdresseTBbl>(e => e.PersonAdresseId)
.WithMany(b=> b.PersonKostentraegerList)
.HasForeignKey(e => e.KostentraegerAdresseId)

;

Ich erhalte folgenden Fehler:

Fehlermeldung:
The relationship from 'PersonKostentraegerTbl.KostentraegerAdresse' to 'PersonAdresseTbl.PersonKostentraegerList' with foreign key properties {'KostentraegerAdresseId' : Nullable<int>} cannot target the primary key {'AdresseId' : int, 'PersonId' : int} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.

Wie kann ich das am besten realisieren?

Ich bedanke mich für Anregungen.

Schicken Sonntagabend noch.

16.834 Beiträge seit 2008
vor 5 Jahren

Steht in der Fehlermeldung: Configure a principal key or a set of compatible foreign key properties for this relationship.

Dafür gibt es im Mapping die HasPrincipalKey-Methode; Du setzt im Mapping nirgends n Principal Key.

S
sronny Themenstarter:in
6 Beiträge seit 2019
vor 5 Jahren

Also ich bin ziemlich sehr neu, hatte vorher in VBA mit Access-Datenbank und ADO gearbeitet.

Principal Keay habe ich auch schon versucht zu verwenden.


            modelBuilder.Entity<PersonKostentraegerTbl>()
                .HasOne<PersonAdresseTbl>(pk => pk.KostentraegerAdresse)
                .WithMany(pa => pa.PersonKostentraegerList)
                .HasPrincipalKey(a => a.PKAdresseID)
                .OnDelete(DeleteBehavior.Restrict);


dazu habe ich eine extra Property eingefügt in PersonadresseTbl:



public class PersonAdresseTbl
{

public int Id {get;set;}

public int PKAdresseId get;set;}
public PersonKostentraegerTbl PKAdresse

public int PersonId{get;set}

public int AdresseId {get;set;}


public virtual PersonTbl Person {get;set;}
public virtual AdresseTbl Adresse {get;set;}

public virtual ICollection<PersonKostentraegerTbl> PersonKostentraegerList {get;set;}

}


Dann erhalte ich bei

update-database die Fehlermeldung:
Fehlermeldung:
Cascading foreign key 'FK_PersonenKostentraeger_Adressen_Id' cannot be created where the referencing column 'PersonenKostentraeger.Id' is an identity column.
Could not create constraint or index. See previous errors.

16.834 Beiträge seit 2008
vor 5 Jahren

Dein Code ist <extrem> anstrengend zu lesen, alles heisst irgendwie Entity.
Kannst Du nicht mit richtigen Bezeichnern arbeiten?

Dann kann man das Ganze hier als Helfer auch potentiell besser nachvollziehen....

S
sronny Themenstarter:in
6 Beiträge seit 2019
vor 5 Jahren

Hab das jetzt mal geändert.

16.834 Beiträge seit 2008
vor 5 Jahren

Mehrere Dinge:

Verwende die Empfehlungen wie Namen verwendet werden. PersonAdresseTbl würde laut Namen eine Tabelle repräsentieren - tut es aber nicht. Es ist eine Entität -> PersonAdresseEntity und vermeide Abkürzungen wie "PK"
Quellcode macht zudem immer Sinn in Englisch. Ansonsten hast Du ein riesen Mischmasch, der sich alles andere als angenehm liest.
Zudem sollte ein Name nicht den Datentyp beinhalten.
[Artikel] C#: Richtlinien für die Namensvergabe

Gruppier die Eigenschaften, wenn Dir die Übersichtlichkeit schwer fällt.


public class PersonAdresseEntity
{
   public int PersonAdressId {get;set;}

   public int PKAdresseId get;set;}
   public PersonKostentraegerEntity PersonKostentraeger

   public int PersonId{get;set}
   public virtual PersonEntity Person {get;set;}

   public int AdressId {get;set;}
   public virtual AdresseEntity Adresse {get;set;}

   public virtual ICollection<PersonKostentraegerEntity> PersonKostentraeger {get;set;}

}

Jeder Deine Entity braucht ein Primary Key, der auch im ModelBuilder definiert sein muss (=> HasKey-Methode).
Im ModelBuilder musst Du dann jede Entity mappen. Dabei dann beachten, dass Du keine Circular References erstellst - also Endlosreferenzen zwischen Mappings.

Alleinstehende Entitäten können einfach definiert werden:

modelBuilder.Entity<PersonEntity>()
   .ToTable("MyPersonTable")
   .HasKey (e => e.Id)
   .Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Aber dann eben das komplette Mapping in M:N Situationen.

modelBuilder.Entity<PersonCostUnitEntity>()
   .ToTable("MyPersonCostUnitTable")
   .HasKey (e => e.Id)
   .Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
   .HasOne<PersonAdresseTbl>(pk => pk.KostentraegerAdresse)
   .WithMany(pa => pa.PersonKostentraegerList)
   .HasForeignKey(p => p.PersonAddressId);
                .OnDelete(DeleteBehavior.Restrict);

Bei einer M:N Tabelle hast Du jedoch durchaus je nach Fall einen Primary Key, der sich aus den jeweiligen Foreign Keys der M:N Beziehung bildet.

Tipp: mach http://www.entityframeworktutorial.net durch.
Das sollte 90% aller Grundfragen beantworten.

S
sronny Themenstarter:in
6 Beiträge seit 2019
vor 5 Jahren

Ich danke dir für deine ausführlichen Informationen. Werde das auch im nächsten Schritt alles gleich ändern.

Bevor ich damit jetzt anfange, kurze Frage noch:

Mit

.HasOne<PersonAdresseTbl>(pk => pk.KostentraegerAdresse)
   .WithMany(pa => pa.PersonKostentraegerList)
   .HasForeignKey(p => p.PersonAddressId);

komme ich bei HasForeignKey nicht auf p=> p.PersonAdressId, da p dann PersonKostentraeger referenziert. Und das klappt derzeit ja noch nicht...

Vielleicht, wenn ich alles mal angepasst habe...

Werde dann jetzt mal damit anfangen...

16.834 Beiträge seit 2008
vor 5 Jahren

Ich hab den Code hier im Editor geschrieben; kann gut sein, dass hier ein Fehler drin ist.
Hab den Code ja auch nicht vor mir.

Es geht darum, dass Du den FK manuell modellieren musst, wenn Du Dich nicht an die Namenskonventionen hälst (was Du eben nicht tust).