Entity Framework: C'è un modo per verificare se il contesto ha un oggetto?
-
21-08-2019 - |
Domanda
Situazione:. Oggetto in sessione da un contesto passato non può essere impostata come genitore di un altro oggetto in quanto altro oggetto si trova in un nuovo contesto
Di 'Ho un utente in sessione che avevo recuperato da un contesto. Ora la pagina viene ricaricata, questo contesto è stato respinto, e un nuovo contesto viene fatto.
someUser = context.First(user => user.id == id);
Session["SomeUser"] = someUser
...
context.Dispose();
Pagina Ricarica
userAddress = new UserAddress();
userAddress.User = (User)Session["SomeUser"]; //BOOM NOT IN SAME CONTEXT
Quello che vorrei fare è:
if(!context.SomeUsers.Contains((User)Session["SomeUSer"]) //Only check context NOT DATABASE
{
//Reload from database
//Set user in session to new object
}
L'idea è che se l'oggetto in sessione non appartiene al contesto attuale, ricaricare dal database in modo che sia ora "di proprietà" dello stesso contesto, come ogni altro oggetto nel contesto attuale. (Sto usando un contesto per ogni richiesta)
Aggiorna
Quindi ho fatto questo temporaneamente fino a quando posso ottenere una migliore idea di come risolvere questo:
Int32 sessionUser = sessionUser .UserID;
var userCheck = EntityContext.Context.ChatUsers.First(item => item.UserID == returnValueID);
if (userCheck != sessionUser)
{
sessionUser = userCheck;
}
L'idea è quella di vedere se l'oggetto in sessione (sessionUser) è la stessa di quella "in" contesto. Ora il caso funziona bene. La prima volta che si crea il contesto, che dovrebbe colpire il database e afferrare l'utente. Una volta a confronto, è ovvio che non sono la stessa ed il sesionUser è ora l'utente nel contesto. La prossima volta che se è selezionata, il sessionUser e userToCheck sono gli stessi.
Il problema è ancora il:
var userCheck = EntityContext.Context.ChatUsers.First(item => item.UserID == returnValueID);
colpisce SEMPRE il database. Questa non è una buona soluzione.
altri Aggiorna
Meh questo può essere la risposta, dopo tutto. Avevo dimenticato questa regola:
x è una proprietà di tipo ObjectQuery. Quando si esegue un ObjectQuery, esso sarà sempre colpito l'archivio di backup. Questo è quello che fanno. Se non si desidera per eseguire una query di database, quindi non utilizzare un ObjectQuery.
Soluzione
Ok capito.
ChatUser userCheck = (ChatUser)EntityContext.Context.GetObjectByKey(returnValue.EntityKey);
if(userCheck != returnValue)
{
sessionUser = userCheck;
}
Il metodo GetObjectByKey che viene descritta come:
GetObjectByKey cerca di recuperare un oggetto che è specificato EntityKey dal ObjectStateManager. Se l'oggetto non è attualmente caricato nel contesto oggetto, una query è eseguita nel tentativo di riportare la oggetto dalla sorgente dati.
Ha fatto alcuni test e fa quello che dice. La prima volta (contesto è stato creato su richiesta) colpisce il database e verifica che obiettano contro ciò che è in sessione. I due non sono le stesse in modo che imposta il sessionUser al nuovo oggetto, così ora avente la sessionUser nel contesto e in sessione. La prossima volta attorno al metodo GetObjectByKey controlla solo il contesto (come Profiler ha mostrato alcuna interazione del database). Yay.
Altri suggerimenti
Perché non basta controllare l'ID utente?
context.Users.Any(user => user.Id = ((User)session["SomeUser"]).Id)
Oppure si potrebbe semplicemente staccare l'oggetto utente dal vecchio contesto e collegarlo al nuovo contesto utilizzando Context.Attach ().