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 è

È stato utile?

Soluzione

Lavorare con oggetti disconnessi ha bisogno di codice extra.

.

Se stai lavorando con oggetti disconnessi, è necessario gestire manualmente la sincronizzazione.

Source

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 a db.Entry(instance).State = EntityState.Added;
  • db.Set<T>().Attach(instance) equivale a db.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 .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top