Ho provato a caricare le proprietà di navigazione prima usando Include
, e mi sono assicurato che i bambini fossero caricati.
Per i nuovi elementi, posso aggiungere un set di navigazione per bambini senza problemi. Per gli articoli aggiornati, ho provato a passare una raccolta completamente nuova per sovrascrivere l'elenco, ma ho letto che avevo bisogno di lavorare con la raccolta caricata. Anche dopo aver eliminato la raccolta e aggiunta ad essa, non vedo alcuna modifica riflessa.
Per tutte le entità nel mio progetto, sto chiamando un metodo generico che ha queste righe e qualche logica di gestione degli errori, ma non vengono lanciati errori:
Metodo Save ():
context.Set<T>().AddOrUpdate(entities);
context.SaveChanges();
Uso:
var entities = repository.LoadWithIncludes(x =>.Subset1);
var entity = entities.FirstOrDefault(x => x.ID == id) ?? new Entity{ID = id};
entity.Subset1.Clear();
var IDs = GetIDs(id) ?? Array.Empty<int?>();
foreach (var id in IDs)
{
entity.Subset1.Add(new Subset
{
ParentId = id,
Value = part1;
});
}
// then I pass the new and updated items into an array and call the Save() method above
Il metodo LoadWithInclude è preso da questa risposta: https://stackoverflow.com/a/18805096/7096114
AddOrUpdate
Questo metodo dovrebbe essere utilizzato durante la semina del database. Il che mi porta a pensare che otterrai dei comportamenti poveri.
Iniziamo con la correzione del modo in cui si aggiorna il contesto ...
public void Edit(Entity entity)
{
var db = context
.Include(i => i.Subset1)
.Where(i => i.ID == id)
.Single();
// update entity
context.Entry(db).CurrentValues.SetValues(entity);
// delete / clear subset1 from database
foreach (var dbSubset1 in db.Subset1.ToList())
{
if (!entity.Subset1.Any(i => i.ID == dbSubset1.ID))
context.Subset1.Remove(dbSubset1);
}
foreach (var newSubset1 in entity.Subset1)
{
var dbSubset1 = db.Subset1.SingleOrDefault(i => i.ID == newSubset1.Id);
if (dbSubset1 != null)
// update Subset1
context.Entry(dbSubset1).CurrentValues.SetValues(newSubset1);
else
db.Subset1.Add(newSubset1);
}
// save
db.SaveChanges();
}
C'è un ottimo articolo su come ottenere questo risultato in un modo molto più pulito, che implica la creazione di un metodo solo per gestire la proprietà di navigazione in Microsoft Docs qui (guarda circa 3/4 del modo in giù l'articolo per l'esempio) .
Ecco anche una citazione dai documenti.
Per la maggior parte delle relazioni, questo può essere fatto aggiornando i campi chiave esterna o le proprietà di navigazione. Per le relazioni molti-a-molti, Entity Framework non espone direttamente la tabella join, quindi aggiungi e rimuovi entità da e verso le proprietà di navigazione appropriate.