[Linq to SQL] DataContext e Multi-tier...e qualche premessa sbagliata

Altro post su Linq to SQL, che parte dalla lettura del post di Dino, e dai commenti di Marco e Paolo.

I dubbi (leciti) del Dino nazionale: capacità Multi-tier di Linq to SQL, legate al DataContext e alle eventuali modificha apportate in RTM, poi leggevo anche dai commenti sul modo in cui passare le entity da WCF....brrrr...
vediamo un po...

Ho visto un paio di premesse IMHO errate.
Partiamo dal capire bene cosa sia un DataContext.

In ogni ORM che si rispetti, esiste un oggetto con forti responsabilità che viene generalmente definito Contesto di Persistenza (ne ho parlato così tanto che se scrivete Contesto di Persistenza su google mi trovate al secondo posto).

Questo oggetto incorpora le seguenti responsabilità:

Data Mapper: contiene tutta la logica di trasformazione (bidirezionale) di una entity in una o più righe sul database. Ne gestisce per intero tutto il ciclo di vita.
Unit of Work: tiene traccia di tutte le modifiche effettuate alle entity (conservandone lo stato iniziale ) mediante un meccanismo di “introspezione”.
Optimistic Offline Lock: offre la possibilità di lanciare aggiornamenti di una entity sul database, verificando che nel frattempo la entity sul database non abbia subito modifiche (problematica tipica nella gestione concorrenziale).
Identity Map: fornisce un meccanismo mediante il quale ogni richiesta relativa alla stesso dato può restituire la medesima istanza dello stesso, e non una nuova copia della entity.
ContestiDiPersistenza01

Non le ho scritte di getto...fortunatamente le avevo scritte per un articolo pubblicato su ugi prima dell'estate:
http://www.ugidotnet.org/articles/articles_read.aspx?ID=129. Ve lo consiglio.

Per poter lavorare, ogni entity gestita dal nostro ORM (qualunque essa sia) ha bisogno di essere collegata ad un contesto di persistenza.

Il DataContext (che rappresenta il contesto di persistenza di Linq to SQL), è un oggetto di leggera costruzione, wrappa una IDbConnection e ne gestisce l'apertura e la chiusura. Ha anche la responsabilità di gestire eventuali proxy e property lazy delle entity a lui collegate.

Lo "scope" del DataContext è più o meno paragonabile a quello di una connection. Apritelo e chiudetelo al più presto possibile. All'interno dei vostri metodi ad esempio. Se la vostra transazione applicativa (non quella sul DB) è di lunga durata (immaginiamo un processo di business), per ogni fase del processo apriamo un DataContext, appiccichiamo (termine molto colorito) le nostre entity ai DataContext successivi e lavoriamo come se nulla fosse. Poi chiudiamo tutto.
ContestiDiPersistenza02


D'altronde basta anche fare F1 nel nostro VS2008 per ottenere questo aiuto
(ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_system.data.linq/html/18dcdfc5-4021-bb96-6e55-86d4512d6552.htm):

"...The DataContext is the source of all entities mapped over a database connection. It tracks changes that you made to all retrieved entities and maintains an "identity cache" that guarantees that entities retrieved more than one time are represented by using the same object instance.

In general, a DataContext instance is designed to last for one "unit of work" however your application defines that term. A DataContext is lightweight and is not expensive to create..."

Che per chi ha lavorato o lavora da anni con gli ORM, significa trovarsi "a casa propria". Ottimo
E continua anche così:

A typical LINQ to SQL application creates DataContext instances at method scope or as a member of short-lived classes that represent a logical set of related database operations..."

Messa in queste condizioni ogni Contesto di Persistenza non nasce per essere thread safe. E infatti sempre nell'help di Linq to SQL si legge:

"Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe"

Conservarlo in un singleton significa solo volersi fare del male fisico (dal commento capisco che Paolo ha infatti verificato e utilizzato il corretto approccio).

Ancora...

il DataContext NON nasce con il presupposto di essere la valvola per poter avviare un multi-tier. Se immaginiamo una architettura a servizi, tutto il domain model persistito con Linq to SQL, viene recintato e isolato. 
A seconda dei servizi si esporranno Contratti e Dati che non hanno un legame diretto con le entity. Altrimenti violiamo tutti i principi SOA. Passare una entity gestita da Linq to SQL tramite WCF...ma siamo sicuri che sia la strada giusta?

Commenti aperti.

Print | posted on lunedì 26 novembre 2007 18:43

Comments have been closed on this topic.