LINQ to SQL vs LINQ to Entities

In questo post cercherò di spiegare la differenza di approccio nell'uso di LINQ to SQL e LINQ to Entities e per fare questo riprendo il magnifico esempio fatto da Davide Mauri di UGISS [lo User Group Italiano su SQL Server] che mi ha dato l'idea per approfondire l'argomento. Ammetto che è anche una delle domande più frequenti che mi vengono rivolte quando partecipo ad eventi e che spero quindi, almeno in parte, di chiarire.

In breve la differenza è quella che riprendo dal mio post precedente.

Per scaricare l'esempio di Davide, seguete il link  [Aggiornato]

LINQ to SQL è una delle implementazioni di LINQ che sono state rilasciate con Visual Studio 2008. LINQ to SQL è il modo più semplice per poter lavorare con SQL Server usando un nuovo modello di programmazione in C# 3.0 e Visual Basic 9. In questo modo nel nostro linguaggio .NET preferito scriviamo del codice che si avvicina ad una sintassi SQL rendendo di fatto meno complicato far "parlare" le nostre applicazioni fatte di classi, clicli e quant'altro con SQL Server, un DBMS relazionale in cui "vediamo" solo tabelle. Con LINQ to SQL in sostanza mappiamo uno a uno le tabelle di SQL Server con delle classi e grazie al framework messo a disposizione siamo in grado di fare le classiche operazioni di Insert, Update, Delete e Query.

LINQ to Entities è un'altra implementazione di LINQ fatta per parlare con l' ADO.NET Entity Framework (EF), sia l'EF che LINQ to Entities sono attualmente in Beta 3. L'EF è un framework che consentirà agli sviluppatori di lavorare con un maggior livello di astrazione; cioè uno sviluppatore si concentrerà solo sul modello concettuale proprio del modello Entità-Relazione, in maniera indipendente dallo storage sottostante sia esso SQL Server o un altro database. Ad esempio potrò lavorare con un' entità Cliente che potrà mapparsi su uno storage relazione anche su più di una tabella.

Da questa rapida descrizione emerge almeno una considerazione.

  • Il modello ad oggetti usato con EF è diverso da quello usato dal designer di Visual Studio per LINQ to SQL. Possiamo infatti lavorare usando l'EF con relazioni molti-a-molti. Ad esempio possiamo pensare di avere una relazione del tipo autori-libri (cioè un autore può aver scritto più libri e un libro può essere scritto da più autori). Nell'esempio seguente il concetto sarà più chiaro.

ok, vediamo di chiarirci meglio le idee sul codice partendo dall'esempio di Davide: in cui trovate lo stesso database utilizzato prima in un progetto che usa LINQ to SQL e poi uno che usa LINQ to Entities e quindi l'EF.

1) Il Database

Il nostro database potrebbe essere un semplice modello per rappresentare la realtà di un'ipotetica biblioteca, dove un utente[tabella Users] può prendere in prestito [tabella Loans] un libro. Dal punto di vista del nostro esempio ci interessano però le altre tre tabelle quella dei libri [tabella Books] e quella degli autori [Authors]. Che se concettualmente rappresentano una relazione molti-a-molti,dal punto di vista di un database relazione sono mappati come in figura con relazioni uno-a-molti e molti-a-uno, quindi si usa la tebella di "appoggio" BooksAuthors per mantenere le corrette relazioni.

image

Vedremo ora come si comporta il designer di Visual Studio 2008 per creare delle classi su questo database e poi vedremo  come usare EF.

2.1) Designer di Visual Studio 2008

Il designer di Visual Studio 2008 ci dà un grande aiuto nel creare le classi, che potremmo creare anche a mano e che di fatto rappresentano il nostro modello applicativo. Se guardate la figura seguente che è il risultato di tale procedura vi accorgerete che le tre tabelle del nostro database sono state mappate uno a uno con le classi che useremo poi nella nostra applicazione.

Nella figura seguente notate il designer delle classi:

image

Ciò provoca la creazione di classi parziali (ad esempio una per Author, una per BookAuhtor e una per Book).

2.2) Usiamo LINQ to SQL

Avendo tre classi, che fanno parte del nostro DataContext specializzato, cioè della classe con cui ci interfacciamo a livello di codice per fare le operazioni di query,insert, update e delete, se vogliamo inserire un libro scritto da due autori dobbiamo in LINQ to SQL scrivere il codice seguente:

image

In buona sostanza una classe Book, due classi Authors e due classi BookAuthors per mantenere le relazioni. Il codice SQL che viene mandato a SQL Server è il seguente:

image

Quello che succede sul database è quello che ci aspettiamo, viene inserito il primo libro poi il primo autore, quindi avendo l'id generato per l'autore viene inserito un record nella tabella BooksAuthors, per mantenere il legame logico molti-a-molti tra autori e libri.

Vediamo ora cosa cambia con l'EF:

3.1) Designer dell' Entity Framework (EF)

Se usiamo il designer dell' EF, attualmente in CTP 2, vediamo come possiamo descrivere il nostro modello applicativo. Ecco che dall'esempio in questione notiamo subito una cosa interessante: cioè nonostante il database sia quello dell'esempio precedente, possiamo mappare relazioni molti-a-molti come mostrato in figura:

image

Nella nostra applicazione avremo una classe Book ed una Authors da utilizzare, non più come in precedenza la classe di appoggio. A livello di designer la differenza è che abbiamo mappato la relazione molti-a-molti (**)  sulla tabella di appoggio BooksAuthors.

3.2) Usiamo LINQ to Entities

A questo punto usiamo LINQ to Entities per lavorare e inserire un libro associato a due autori. Spero sia chiaro la semplificazione delle istruzioni LINQ che seguono, solo legate alla differenza di approccio concettuale nella strutturazione delle classi. Questo è una delle differenze quando si usa l'EF. Avrei potuto anche mappare il mio database uno-a-uno come fatto con l'esempio di LINQ to SQL, questo è quello che farebbe in automatico il designer se importassimo direttamente il database.

image 

In questo caso, il codice per inserire un libro e due autori utilizza un numero inferiore di classi. In LINQ to Entities non esite la possibilità di tracciare il codice SQL mandato sul database direttamente nella console application.

Conclusione

Nel post avete visto il diverso approccio usato da EF, LINQ to Entities e LINQ to SQL per affrontare un database semplice come quello presentato. L'esempio tende a porre l'attenzione sul supporto di relazioni molti-a-molti. Questa non è l'unica differenza tra le due implementazioni di LINQ, ma è a mio parere quella più significativa.

EF permette di descrivere il proprio modello applicativo pensando al Modello Entità-Relazioni. E' possibile mappare poi il modello creato, sulle tabelle del database relazionale sottostante (sia esso SQL Server o un altro DBMS di quelli che saranno supportati dall 'EF). L'architettura realizzata si basa sull'uso di tre file XML, che in questo post non ho descritto e la cui complessità è nascosta dal Designer. In generale EF sarà più adatto (al momento come vi dicevo è in Beta 3, mentre il designer usato è in CTP) ad ambienti in cui viene richiesto il supporto a database diversi da SQL Server e in cui l'evolzione del database stesso avviene spesso ad opera di persone diverse da quelle che scrivono le applicazioni. In questi scenari è tipico avere un elevato numero di tabelle che rappresentano logicamente un'entità (Cliente ad esempio) o relazione di ereditarietà tra queste (Persone e Cliente).

LINQ to SQL rappresenta la giusta soluzione per realizzare applicazioni RAD o per realizzare applicazioni in cui il mapping più sofisticato di EF non è necessario, in questo scenario LINQ to SQL rappresenta il modo più rapido di lavorare con LINQ e SQL Server.

Vi consiglio la lettura di questo articolo (in Inglese) per ulteriori approfondimenti e spero che questo post sia almeno parzialmente utile a capire il diverso contesto di utilizzo delle due implementazioni di LINQ.

Ciao