Wir möchten eine optionale Eins-zu-Eins-Beziehung mit Entity Framework Code First verwenden. Wir haben zwei Einheiten.
public class PIIUser
{
public int Id { get; set; }
public int? LoyaltyUserDetailId { get; set; }
public LoyaltyUserDetail LoyaltyUserDetail { get; set; }
}
public class LoyaltyUserDetail
{
public int Id { get; set; }
public double? AvailablePoints { get; set; }
public int PIIUserId { get; set; }
public PIIUser PIIUser { get; set; }
}
PIIUser
kann eine haben LoyaltyUserDetail
, LoyaltyUserDetail
muss aber eine haben PIIUser
. Wir haben diese fließenden Ansatztechniken ausprobiert.
modelBuilder.Entity<PIIUser>()
.HasOptional(t => t.LoyaltyUserDetail)
.WithOptionalPrincipal(t => t.PIIUser)
.WillCascadeOnDelete(true);
Dieser Ansatz hat keinen LoyaltyUserDetailId
Fremdschlüssel in der PIIUsers
Tabelle erstellt.
Danach haben wir den folgenden Code ausprobiert.
modelBuilder.Entity<LoyaltyUserDetail>()
.HasRequired(t => t.PIIUser)
.WithRequiredDependent(t => t.LoyaltyUserDetail);
Diesmal hat EF jedoch keine Fremdschlüssel in diesen beiden Tabellen erstellt.
Haben Sie Ideen für dieses Problem? Wie können wir eine eins zu eins optionale Beziehung mit der fließenden API des Entity Frameworks erstellen?
quelle
WithOptional
? Was ist der Unterschied mitWithRequiredDependent
undWithRequiredOptional
?Machen Sie es einfach so, wenn Sie eine Eins-zu-Viele-Beziehung haben
LoyaltyUserDetail
undPIIUser
Ihre Zuordnung so sein sollteEF sollte alle Fremdschlüssel erstellen, die Sie benötigen, und WithMany einfach nicht interessieren !
quelle
Es gibt mehrere Probleme mit Ihrem Code.
Eine 1: 1- Beziehung ist entweder: PK <-PK , wobei eine PK-Seite auch eine FK ist, oder PK <-FK + UC , wobei die FK-Seite eine Nicht-PK ist und eine UC hat. Ihr Code zeigt, dass Sie FK <-FK haben , da Sie beide Seiten als FK definieren, aber das ist falsch. Ich weiß, dass
PIIUser
es die PK-Seite undLoyaltyUserDetail
die FK-Seite ist. Dies bedeutet,PIIUser
dass kein FK-Feld vorhanden ist, dies jedoch derLoyaltyUserDetail
Fall ist.Wenn die 1: 1- Beziehung optional ist, muss die FK-Seite mindestens 1 nullbares Feld haben.
pswg oben hat Ihre Frage beantwortet, aber einen Fehler gemacht, dass er / sie auch eine FK in PIIUser definiert hat, was natürlich falsch ist, wie ich oben beschrieben habe. Definieren Sie also das nullfähige FK-Feld in
LoyaltyUserDetail
, definieren Sie das Attribut inLoyaltyUserDetail
, um es als FK-Feld zu markieren, geben Sie jedoch kein FK-Feld in anPIIUser
.Sie erhalten die Ausnahme, die Sie oben unter dem Beitrag von pswg beschrieben haben, da keine Seite die PK-Seite ist (prinzipielles Ende).
EF ist nicht sehr gut im 1: 1-Bereich, da es nicht in der Lage ist, eindeutige Einschränkungen zu bewältigen. Ich bin kein Experte für Code, daher weiß ich nicht, ob ein UC erstellt werden kann oder nicht.
(Bearbeiten) Übrigens: A 1: 1 B (FK) bedeutet, dass nur 1 FK-Einschränkung erstellt wurde, wobei das Ziel von B auf die PK von A zeigt und nicht 2.
quelle
public class User { public int Id { get; set; } public int? LoyaltyUserId { get; set; } public virtual LoyaltyUser LoyaltyUser { get; set; } } public class LoyaltyUser { public int Id { get; set; } public virtual User MainUser { get; set; } } modelBuilder.Entity<User>() .HasOptional(x => x.LoyaltyUser) .WithOptionalDependent(c => c.MainUser) .WillCascadeOnDelete(false);
Dadurch wird das Problem mit REFERENCE und FOREIGN KEYS gelöst
beim AKTUALISIEREN oder LÖSCHEN eines Datensatzes
quelle
Versuchen Sie, das
ForeignKey
Attribut derLoyaltyUserDetail
Eigenschaft hinzuzufügen :public class PIIUser { ... public int? LoyaltyUserDetailId { get; set; } [ForeignKey("LoyaltyUserDetailId")] public LoyaltyUserDetail LoyaltyUserDetail { get; set; } ... }
Und das
PIIUser
Eigentum:public class LoyaltyUserDetail { ... public int PIIUserId { get; set; } [ForeignKey("PIIUserId")] public PIIUser PIIUser { get; set; } ... }
quelle
ForeignKey
Attribut nur einem Ende der Beziehung hinzufügen ? dh nur amPIIUser
oderLoyaltyUserDetail
.Die eine Sache, die mit den obigen Lösungen verwirrend ist, ist, dass der Primärschlüssel in beiden Tabellen als " Id" definiert ist. Wenn Sie einen Primärschlüssel basierend auf dem Tabellennamen haben, der nicht funktioniert, habe ich die Klassen geändert, um dasselbe zu veranschaulichen. Das heißt, die optionale Tabelle sollte keinen eigenen Primärschlüssel definieren, sondern denselben Schlüsselnamen aus der Haupttabelle verwenden.
public class PIIUser { // For illustration purpose I have named the PK as PIIUserId instead of Id // public int Id { get; set; } public int PIIUserId { get; set; } public int? LoyaltyUserDetailId { get; set; } public LoyaltyUserDetail LoyaltyUserDetail { get; set; } } public class LoyaltyUserDetail { // Note: You cannot define a new Primary key separately as it would create one to many relationship // public int LoyaltyUserDetailId { get; set; } // Instead you would reuse the PIIUserId from the primary table, and you can mark this as Primary Key as well as foreign key to PIIUser table public int PIIUserId { get; set; } public double? AvailablePoints { get; set; } public int PIIUserId { get; set; } public PIIUser PIIUser { get; set; } }
Und dann gefolgt von
Würde den Trick machen, die akzeptierte Lösung kann dies nicht klar erklären, und es warf mich für ein paar Stunden ab, um die Ursache zu finden
quelle
Dies ist für das Originalposter nicht von Nutzen, aber für alle, die noch auf EF6 arbeiten und benötigen, dass sich der Fremdschlüssel vom Primärschlüssel unterscheidet, gehen Sie wie folgt vor:
public class PIIUser { public int Id { get; set; } //public int? LoyaltyUserDetailId { get; set; } public LoyaltyUserDetail LoyaltyUserDetail { get; set; } } public class LoyaltyUserDetail { public int Id { get; set; } public double? AvailablePoints { get; set; } public int PIIUserId { get; set; } public PIIUser PIIUser { get; set; } } modelBuilder.Entity<PIIUser>() .HasRequired(t => t.LoyaltyUserDetail) .WithOptional(t => t.PIIUser) .Map(m => m.MapKey("LoyaltyUserDetailId"));
Beachten Sie, dass Sie das
LoyaltyUserDetailId
Feld nicht verwenden können, da es, soweit ich das beurteilen kann, nur mit der fließenden API angegeben werden kann. (Ich habe drei Möglichkeiten ausprobiert, dies mit demForeignKey
Attribut zu tun , und keine davon hat funktioniert).quelle