La nuova sottotensione non salverà quando viene salvato l'entità genitore
-
02-01-2020 - |
Domanda
Ho un'entità genitore
foo
che esiste nel DB, ho una proprietà bar
su questa entità (una a molte relazioni).
Foo
è staccato perché è deseriabilizzato utilizzando Webapi, quindi lo faccio a foo
context.Foos.AddOrUpdate(foo);
.
Anche se c'è un nuovo riferimento bar
ad esso, non verrà salvato, tuttavia funziona così per un'altra relazione che abbiamo molte a molte relazioni.Se aggiungo una nuova entità a quella raccolta, verrà salvato sul suo tavolo e anche una riga viene aggiunta alla tabella dei rapporti.
Se i context.Bars.AddOrUpdate(foo.Bar);
prima di chiamare context.Foos.AddOrUpdate(foo);
salverà correttamente la nuova barra nella tavola della barra, ma non aggiungerà il corretto barid alla tabella FOO
@yuliam chandra
Se capisco correttamente la tua risposta (penso che tu stia mescolando barre e foos nella tua risposta) questo dovrebbe funzionare?
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
.
Ma non è
Soluzione
Lavorare con oggetti disconnessi ha bisogno di codice extra.
.Se stai lavorando con oggetti disconnessi, è necessario gestire manualmente la sincronizzazione.
Se Bar
è un'entità esistente è necessario allenarla prima, quindi Foo
verrà aggiunto come bambini Bar's
.
if (foo.Bar.Id != 0)
{
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
}
.
L'esempio del codice sopra è simile con Course
(Foo
) e Department
(Bar
) in Questo articolo .
Ma se Bar
è una nuova entità è solo necessario aggiungere Foo
, verrà aggiunto anche Bar
.
else
{
context.Foos.Add(foo);
}
.
Alcune altre varietà possono essere controllate su La mia risposta .
Aggiorna
Prima di spiegare ulteriormente, vorrei mostrare un codice identico.
- .
-
db.Set<T>().Add(instance)
equivale adb.Entry(instance).State = EntityState.Added;
-
db.Set<T>().Attach(instance)
equivale adb.Entry(instance).State = EntityState.Unchanged;
La risposta precedente ha spiegato circa due condizioni.
- .
-
Nuova barra foo e esistente
context.Bars.Attach(foo.Bar);
context.Foos.AddOrUpdate(foo);
-
Nuovo foo e nuovo bar
context.Foos.Add(foo);
Aggiunto speciale
Added
ha una condizione speciale, una volta che un'entità è contrassegnata come Added
. Tutte le entità nel grafico saranno contrassegnate come anche Added
, anche se qualsiasi entità di riferimento è un oggetto esistente nel database. Se avremo questo codice, verrà aggiunto FOO e BAR.
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Foo>().Add(foo);
db.SaveChanges();
.
Per impedire che l'accada, la barra deve essere allegata prima.
var foo = new Foo (); // new foo
foo.Bar = new Bar { BarId = 123 }; // existing bar
db.Set<Bar>().Attach(bar);
db.Set<Foo>().Add(foo);
db.SaveChanges();
.
Check Julie Lerman Articolo per una spiegazione più completa. .
.Il motivo per cui succede è che quando si utilizza il metodo DbSet.add (quello è, screencasts.add), non solo lo stato dell'entità della radice contrassegnata "Aggiunto," ma tutto nel grafico che il contesto non era precedentemente consapevole di è segnato anche aggiunto. Anche se lo sviluppatore può essere consapevole che l'argomento ha un valore ID esistente, un quadro di entità onora il suo entitystate (aggiunto) e crea un comando di inserimento del database per l'argomento, indipendentemente dall'ID esistente.
Regola la spiegazione in base al tuo aggiornamento
E la tua domanda aggiornata riguarda Foo e New Bar esistenti. Usando il tuo codice, il risultato non aggiungerà nuova barra e FOO esistente non effettuerà una relazione con New Bar.
var foo = new Foo();
foo.FooId = 524 //Existing foo;
foo.Bar = new Bar(); //Completely new bar
db.Foos.AddOrUpdate(foo);
db.SaveChanges();
.
Se aggiungiamo manualmente la barra insieme a AddOrUpdate(foo)
, il risultato non è ancora così come previsto. Verrà aggiunta la nuova barra, ma FOO non avrà una relazione con il nuovo bar.
db.Bars.Add(foo.Bar);
db.Foos.AddOrUpdate(foo);
.
Il comportamento del AddOrUpdate
è incoerente.
Soluzione
.Se stai lavorando con oggetti disconnessi, è necessario gestire manualmente la sincronizzazione.
Questo codice dovrebbe funzionare in tutte le condizioni.
- .
- New Foo e New Bar
- Nuovo foo e barra esistente
- Esistente Foo e New Bar
- Esistente foo e barra esistente
Questo codice dipende dall'ID (ID= 0 è una nuova entità).
db.Entry(foo).State =
foo.FooId == 0 ? EntityState.Added : EntityState.Modified;
if (foo.Bar != null)
{
db.Entry(foo.Bar).State =
foo.Bar.BarId == 0 ? EntityState.Added : EntityState.Modified;
^^^
// If you don't want to change the Bar while creating a relationship between
// Foo and with existing Bar, you can change
// `EntityState.Modified` with `EntityState.Unchanged`
}
db.SaveChanges();
.
relativo a AddOrUpdate
, penso che ci sia un problema aperto che può essere trovato qui .