Sto facendo fatica a capire qualcosa con il rilevamento dei cambiamenti in EF6.
Ho un codice simile a questo.
public class SomeClass
{
private List<User> _users;
private DAL _dal;
public void ProcessUsers()
{
_users = _dal.GetUsers();
foreach(var u in users)
{
u.user.Comment = "This is a test";
}
_dal.SaveChanges();
}
}
La classe DAL sembra un po 'come questa.
public class DAL
{
...
private DataContext _context; // Assume that this is being newed up in a constructor.
public List GetUsers()
{
return _context.Users.ToList();
}
public void SaveChanges()
{
_context.SaveChanges();
}
}
Quindi, come possiamo vedere dal codice nel metodo ProcessUsers, abbiamo una lista di utenti e stiamo modificando quella lista.
Ora so che questo funziona, è come l'ho sempre fatto, ma ho sempre avuto l'impressione che gli oggetti nella lista (gli utenti in questo caso) fossero un riferimento all'oggetto corrispondente nella raccolta locale di DBSet.
Dopo un po 'di riflessione non sono sicuro che sia così, come se il contesto fosse disposto, l'elenco è ancora popolato e può essere manipolato (perdiamo la possibilità di reinserirlo nel database senza un lavoro aggiuntivo), quindi da quello prospettiva gli elementi nell'elenco devono essere copie degli elementi dalla raccolta locale di DBSet ... ma in tal caso non avrei comunque pensato che la manipolazione di un oggetto nell'elenco avrebbe avuto qualche effetto sull'oggetto nel dbset come sarebbe una copia.
In sintesi
La domanda è: cosa succede quando chiamo ToList su un DBSet e come funziona il monitoraggio delle modifiche in questa istanza? - So che funziona, ma penso che la mia attuale comprensione potrebbe essere errata.
EF ha una collezione in cui sono tracciate tutte le modifiche in sospeso ( _context.ObjectStateManager
, vedi qui ... ). Inoltre, più entità di caricamento con EF ottieni un'istanza proxy invece della tua vera classe entità. Utilizzando questo proxy EF sta "iniettando" il codice nelle istanze delle entità che aggiorna le informazioni di tracciamento delle modifiche.
Quando elimini il tuo contesto perdi queste informazioni. Per aggiungere l'istanza dell'entità esistente a un altro contesto, è possibile utilizzare il metodo _context.Attach()
.
SaveChanges()
elabora le informazioni di _context.ObjectStateManager
.