Qui ci sono due problemi, quello ovvio, mostrato nell'eccezione. Quando si definisce una relazione uno-a-uno, l'FK deve essere anche il PK. In questo caso il PK e FK di entrambe le entità sono il campo Id
. Il problema mostrato nell'eccezione è che l'FK è generato dal database. Pertanto, se si inserisce uno Child1
con un valore Child2
correlato, EF non ha modo di impostare il valore FK del relativo Child2
perché è generato dal database.
Il secondo problema, che non si è ancora verificato, è che una relazione uno-a-uno è solo una cosa teorica in un database come SQL Server. Se si desidera inserire Child1
che dipende da Child2
, è necessario inserire prima Child1
e quindi il relativo Child2
. È giusto, ma, ooops, devi anche inserire Child2
prima di inserire Child1
, perché Child1
dipende anche da Child2
. Quindi, avere una relazione pura uno a uno non è possibile.
per risolvere questo problema è necessario fare due cose:
- rendere il rapporto di 1-to-(0 o 1). Cioè devi avere un'entità principale e un'entità dipendente che può o non può esistere. Ciò consentirà di inserire l'entità principale, senza l'entità dipendente, poiché con questa configurazione non è possibile impostare l'entità senza la dipendenza.
- il PK principale può essere lasciato come database generato, ma è necessario modificare il PK sull'entità dipendente per non generare DB. Quindi, quando si inserisce l'entità dipendente, il PK, che è anche l'FK, può essere liberamente specificato da EF.
Infine, se ci pensate, una relazione 1-a-1 di solito non ha senso. È possibile utilizzare una singola tabella che contiene tutte le colonne in entrambe le tabelle, poiché quando esiste una riga nella tabella A, deve esistere nella tabella B e viceversa. Quindi avere un solo tavolo ha lo stesso effetto.
Tuttavia, se si vuole ancora utilizzare il rapporto 1 a 1, EF permette di modellare in questo modo:
modelBuilder.Entity<Child1>()
.HasRequired(c1 => c1.Child2)
.WithRequiredPrincipal(c2 => c2.Child1);
Si noti che, in questo caso, l'astrazione EF si prende cura per consentire avere una relazione 1 a 1, anche se non può esistere nel DB. Tuttavia, è necessario specificare questa relazione utilizzando ModelBuilder
perché è necessario specificare un principal e un lato dipendente. In questo caso il principale è Child1
e il dipendente è Child2
. Si noti che è ancora necessario fare attenzione con la regola per i valori generati dal database.
Si noti che questo è modellato nel DB con un singolo FK da Child2
a Child1
, e non FK da Child1
a Child2
. Quindi, nel DB è una relazione (1) a (0 o 1), come spiegato sopra
public class Child1
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] // Leave as is
public int Id { get; set; }
...
public class Child2
{
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[DatabaseGenerated(DatabaseGeneratedOption.None)] // Not db-generated
//[ForeignKey("Child1")] -- specified in the model builder
public int Id { get; set; }
Grazie. Il motivo per cui uso la relazione 1: 1 è che, dobbiamo separare il modello Child1 e Child2 a causa di altri componenti che hanno bisogno di queste due classi. E a proposito, puoi pubblicare le classi di modelli modificate per mostrare quali modifiche devo adattare per i due modelli precedenti, dato che aggiungo la configurazione del builder del modello, ha ancora lo stesso errore. –
Ho aggiornato la mia risposta con il modello modificato. Ricorda che, dato che stai lavorando con una relazione 1 a 1, e 'Child2' dipende da' Child1', il suo 'Id' sarà copiato dal relativo' Child1' quando lo crei. NOTA: se hai solo una tabella, ci sono altri modi per risolvere questo problema: per esempio potresti modificare gli altri componenti per richiedere 'IChild1' e' IChild2' e implementare tali interfacce sull'unica entità esistente, o usare i mapper (AutoMapper , ValueInjecter). Non so come appare la tua app e se questo potrebbe funzionare per te. – JotaBe
Genera nuova eccezione: '{" Impossibile inserire il valore esplicito per la colonna Identity nella tabella 'Child2' quando IDENTITY_INSERT è impostato su OFF. "}', Cosa significa? Il codice completo può essere visto [qui] (https://gist.github.com/JerryBian/8ed6605453adaed579b2). –