Partendo da questo ottimo articolo di Janky, ho fatto fatto qualche prova con il metodo Attach del DataContext ottenendo dei risultati inizialmente inattesi che comunque rispettano quello che è il comportamento tipico del DataContext.
Ho utilizzato questo banale esempio con l'intento di simulare uno scenario:
- Pagina1: Leggo un dato e lo modifico
- Pagina2: Visualizzo il rapporto e confermo le modifiche.
Customer cust;
//Page1, read customer, updates City property
using(MyDataContext db1 = newMyDataContext())
{
db1.ObjectTrackingEnabled = false;
cust = db1.Customers.Where(c => c.CustomerID == "ALFKI").SingleOrDefault();
}
cust.City = (cust.City=="Paris")? "Berlin":"Paris";
//Here customer should be saved to session...
//Page2, gets customer from session, display report then user confirm saving...
using(MyDataContext db2 = newMyDataContext())
{
db2.Log=Console.Out;
db2.Customers.Attach(cust);
db2.SubmitChanges();
}
Il risultato è che nulla viene memorizzato sebbene Customer sia stato modificato, affinchè ciò avvenga dovrei modificare l'istanza in Page2 ma non è ciò che mi ero preposto.
Come descritto su MSDN, Attach ha degli overload che permettono di marcare l'entità come "modificata" oppure di fornire un entità da utilizzare come riferimento per capire quali campi devono essere aggiornati.
A prima vista il secondo caso potrebbe sembrare quello ottimale, sta di fatto che, cachare l'istanza originale non è proprio così banale (o perlomeno è parecchio noioso) e le classi generate dal designer non sono serializzabili, mentre il primo caso che consiste nel modificare il codice in:
using (MyDataContext db2 = new MyDataContext())
{
db2.Log=Console.Out;
db2.Customers.Attach(cust,true);
db2.SubmitChanges();
}
genera un eccezione: System.InvalidOperationException was unhandled
Message="An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy."
eccezione che si può eliminare togliendo il controllo di concorrenza cambiando l'attributo UpdateCheck a None via designer.
[Column(Storage="_Fax", DbType="NVarChar(24)", UpdateCheck=UpdateCheck.Never)]
public string Fax ...
Ovviamente questa soluzione non mi piace neanche un po'...
Morale della favola: Sicuramente ci sono soluzioni più smart per ottenere lo stesso risultato, in primis quello di agire sul DB direttamente da Page2
ma sta di fatto che il metodo Attach va gestito con molta attenzione.
Technorati Tags:
LINQ,
Attach method