NHibernate vs LINQ to SQL


117

Come qualcuno che non ha utilizzato nessuna delle due tecnologie su progetti del mondo reale, mi chiedo se qualcuno sappia come queste due si completano a vicenda e quanto le loro funzionalità si sovrappongono?

Risposte:


113

LINQ to SQL ti obbliga a usare il modello tabella per classe. I vantaggi dell'utilizzo di questo modello sono che è veloce e facile da implementare e richiede uno sforzo minimo per far funzionare il dominio in base a una struttura di database esistente. Per applicazioni semplici, questo è perfettamente accettabile (e spesso anche preferibile), ma per applicazioni più complesse gli sviluppatori suggeriscono spesso di utilizzare invece un modello di progettazione basato sul dominio (che è ciò che NHibernate facilita).

Il problema con il modello tabella per classe è che la struttura del database ha un'influenza diretta sulla progettazione del dominio. Ad esempio, supponiamo di avere una tabella Clienti con le seguenti colonne per contenere le informazioni sull'indirizzo principale di un cliente:

  • Indirizzo
  • Città
  • Stato
  • Cerniera lampo

Supponiamo ora che tu voglia aggiungere colonne anche per l'indirizzo postale del cliente in modo da aggiungere le seguenti colonne alla tabella Clienti:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

Utilizzando LINQ to SQL, l'oggetto Customer nel tuo dominio ora avrebbe proprietà per ciascuna di queste otto colonne. Ma se stavi seguendo un modello di progettazione basato sul dominio, probabilmente avresti creato una classe Indirizzo e la tua classe Cliente avrebbe avuto due proprietà Indirizzo, una per l'indirizzo postale e una per l'indirizzo corrente.

Questo è un semplice esempio, ma dimostra come il modello tabella per classe può portare a un dominio un po 'maleodorante. Alla fine, tocca a te. Ancora una volta, per app semplici che necessitano solo della funzionalità CRUD (creazione, lettura, aggiornamento, eliminazione) di base, LINQ to SQL è l'ideale per la semplicità. Ma personalmente mi piace usare NHibernate perché facilita un dominio più pulito.

Modifica: @lomaxx - Sì, l'esempio che ho usato era semplicistico e avrebbe potuto essere ottimizzato per funzionare bene con LINQ to SQL. Volevo mantenerlo il più semplice possibile per portare a casa il punto. Tuttavia, resta il punto che esistono diversi scenari in cui avere la struttura del database per determinare la struttura del dominio sarebbe una cattiva idea, o almeno porterebbe a una progettazione OO non ottimale.


4
Puoi codificare l'implementazione del tuo repository usando Linq To SQL, è molto utile.
Nicolas Dorier

1
Penso che non sia ActiveRecord, anche le classi mappate incapsulano parte della logica dell'infrastruttura. Il pattern ActiveRecord sarebbe se potessi avere Customer.Save (). L2S implementa il pattern Unit of Work con la classe DataContext, come Session in nHibernate, ma NH ha un vero approccio POCO.
Hrvoje Hudo

1
@kevin "LINQ to SQL utilizza il modello di record attivo" Non è corretto. È come dire che ADO.NET utilizza il record attivo o NHibernate utilizza il record attivo. Sono tutte tecnologie di accesso ai dati e non applicano alcun modello di accesso ai dati particolare. Personalmente mi piace usare linq-to-sql con il pattern del repository. Hai ragione sul fatto che linq-to-sql non supporta i mapping complessi come fa NHibernate.
liammclennan

1
Che ne dici invece di normalizzare il tuo database e lasciare che il tuo DAL venga generato da strumenti come SQLMetal?
Alex

3
@CoffeeAddict Quando la mancata corrispondenza dell'impedenza è troppo da sopportare, è allora che la tua applicazione è troppo complicata per usare LINQ to SQL su, imo. Il motivo per cui il mio esempio è puzzolente è perché l'uso di LINQ to SQL comporterebbe 8 proprietà invece di 2 e limita la tua capacità di fare cose come implementare funzioni che accettano una classe Address o implementare routine sulla classe Address che saresti in grado di fare fare se hai usato NHibernate.
Kevin Pang

26

Due punti che sono stati persi finora:

  • LINQ to SQL non funziona con Oracle o con qualsiasi database diverso da SqlServer. Tuttavia, le terze parti offrono un supporto migliore per Oracle, ad esempio dotConnect di devArt , DbLinq , Mindscape's LightSpeed e ALinq . (Non ho alcuna esperienza personale con questi)

  • Da Linq a NHibernate puoi usare Linq con un Nhiberate, quindi potrebbe rimuovere un motivo per non usarlo.

Anche la nuova interfaccia fluente a Nhibernate sembra rendere meno doloroso configurare la mappatura di Nhibernate. (Eliminando uno dei punti dolenti di Nhibernate)


Aggiornare

Linq to Nhiberate è migliore in Nhiberate v3 che ora è in alpha . Sembra che Nhiberate v3 possa essere spedito verso la fine di quest'anno.

Anche Entity Frame Work a partire da .net 4 sta iniziando a sembrare un'opzione reale.


2
Linq a NHibernate è ancora in una fase iniziale. Non è un'implementazione completa e, probabilmente, non è affatto pronta per l'uso in produzione.
liammclennan

La nuova versione di LinqConnect 2.0 introduce alcune funzionalità aggiuntive per praticità, come il supporto dell'ereditarietà della tabella per tipo, il supporto PLINQ e la funzionalità degli aggiornamenti batch. ORM Designer (Devart Entity Developer) ora ha il supporto Model First e la funzione di sincronizzazione della mappatura. Maggiori dettagli: devart.com/news/2010/dotconnects600.html
Devart

23

@ Kevin: Penso che il problema con l'esempio che stai presentando sia che stai usando un design di database scadente. Avrei pensato che avresti creato una tabella clienti e una tabella indirizzi e normalizzato le tabelle. Se lo fai, puoi sicuramente utilizzare Linq To SQL per lo scenario che stai suggerendo. Scott Guthrie ha una grande serie di post sull'uso di Linq To SQL che ti consiglio vivamente di dare un'occhiata.

Non penso che si possa dire che Linq e NHibernate si completano a vicenda in quanto ciò implicherebbe che potrebbero essere usati insieme, e sebbene questo sia possibile, è molto meglio sceglierne uno e attenersi ad esso.

NHibernate ti consente di mappare le tabelle del database agli oggetti del tuo dominio in modo altamente flessibile. Consente inoltre di utilizzare HBL per interrogare il database.

Linq to SQL ti consente anche di mappare gli oggetti del tuo dominio al database, tuttavia utilizza la sintassi delle query Linq per interrogare il database

La differenza principale qui è che la sintassi delle query Linq viene controllata in fase di compilazione dal compilatore per garantire che le query siano valide.

Alcune cose da tenere presente con linq è che è disponibile solo in .net 3.x ed è supportato solo in VS2008. NHibernate è disponibile in 2.0 e 3.x così come VS2005.

Alcune cose da tenere presente con NHibernate è che non genera i tuoi oggetti di dominio, né genera i file di mappatura. Devi farlo manualmente. Linq può
farlo automaticamente per te.


15
E se stai scrivendo codice su una struttura di database legacy che non puoi modificare perché supporta altre app. Desideri che il tuo modello di dominio erediti la struttura del database scadente o desideri creare un modello di dominio avanzato che può variare indipendentemente dalla struttura del database?
Larry Foulkrod

7

Fluent NHibernate può generare i file di mappatura in base a semplici convenzioni. Nessuna scrittura XML e fortemente tipizzata.

Di recente ho lavorato a un progetto in cui dovevamo passare da Linq a SQL a NHibernate per motivi di prestazioni. Soprattutto il modo in cui L2S materializza gli oggetti sembra più lento di quello di NHibernate e anche la gestione del cambiamento è piuttosto lenta. E può essere difficile disattivare la gestione delle modifiche per scenari specifici in cui non è necessaria.

Se intendi utilizzare le tue entità disconnesse da DataContext, ad esempio negli scenari WCF, potresti avere molti problemi a connetterle nuovamente a DataContext per aggiornare le modifiche. Non ho avuto problemi con NHibernate.

La cosa che mi mancherà da L2S è principalmente la generazione di codice che mantiene le relazioni aggiornate su entrambe le estremità delle entità. Ma immagino che ci siano alcuni strumenti per NHibernate per farlo anche là fuori ...


2
Nel caso in cui altri leggessero il tuo post e stessero pensando di abbandonare la nave, .ObjectTrackingEnabled = falsesul tuo DataContextavresti risolto il tuo problema di rilevamento delle modifiche. Fintanto che si accetta il modello di unità di lavoro e non si cerca di fare DDD, Linq-to-SQL offre davvero.
mattmc3

" Avevamo bisogno di passare da Linq a SQL a NHibernate per motivi di prestazioni " - Avendo usato [Fluent, nient'altro] NHibernate per alcuni anni, mi sento per te. Penso che per lo più abbiamo imbrogliato e abbiamo finito per scrivere SQL nativo per punti di pressione sulle prestazioni reali. Sarebbe interessante sentire un aggiornamento (sei anni dopo ...) su come è andata la tua migrazione e se ne è valsa la pena.
ruffin

5

Puoi chiarire cosa intendi per "LINQ"?

LINQ non è una tecnologia di accesso ai dati, è solo una funzionalità del linguaggio che supporta l'esecuzione di query come costrutto nativo. Può interrogare qualsiasi modello a oggetti che supporti interfacce specifiche (ad esempio IQueryable).

Molte persone si riferiscono a LINQ To SQL come LINQ, ma non è affatto corretto. Microsoft ha appena rilasciato LINQ To Entities con .NET 3.5 SP1. Inoltre, NHibernate ha un'interfaccia LINQ, quindi puoi usare LINQ e NHibernate per ottenere i tuoi dati.


2

Con LINQ, presumo che tu intenda LINQ to SQL perché LINQ, di per sé, non ha alcun database associato ad esso. È solo un linguaggio di query che ha un carico di barca di zucchero sintetico per farlo sembrare SQL-ish.

Negli esempi di base di base, NHibernate e LINQ to SQL sembrano risolvere entrambi lo stesso problema. Una volta ottenuto il superamento, ti renderai presto conto che NHibernate supporta molte funzionalità che ti consentono di creare modelli di dominio davvero ricchi. Esiste anche un progetto LINQ to NHibernate che consente di utilizzare LINQ per eseguire query su NHibernate più o meno allo stesso modo in cui utilizzeresti LINQ to SQL.


1

Per prima cosa separiamo due cose diverse: la modellazione di database si occupa dei dati mentre la modellazione di oggetti si occupa di entità e relazioni.

Il vantaggio di Linq-to-SQL consiste nel generare rapidamente classi dallo schema del database in modo che possano essere utilizzate come oggetti record attivi (vedere la definizione del modello di progettazione del record attivo).

Il vantaggio di NHibernate consiste nel consentire flessibilità tra la modellazione degli oggetti e la modellazione del database. Il database può essere modellato per riflettere al meglio i dati, ad esempio prendendo in considerazione le prestazioni. Mentre la modellazione a oggetti rifletterà al meglio gli elementi della regola aziendale utilizzando un approccio come Domain-Driven-Design. (vedi il commento di Kevin Pang)

Con database legacy con scadenti convenzioni di modellazione e / o denominazione, Linq-to-SQL rifletterà queste strutture e nomi indesiderati alle tue classi. Tuttavia NHibernate può nascondere questo pasticcio con i mappatori di dati.

Nei progetti greenfield in cui i database hanno una buona denominazione e una bassa complessità, Linq-to-SQL può essere una buona scelta.

Tuttavia è possibile utilizzare Fluent NHibernate con le mappature automatiche per questo stesso scopo con la mappatura come convenzione. In questo caso non ti preoccupi di nessun mappatore di dati con XML o C # e lascia che NHibernate generi lo schema del database dalle tue entità in base a una convenzione che puoi personalizzare.

D'altra parte la curva di apprendimento di Linq-to-SQL è più piccola di NHibernate.


0

Oppure potresti usare il progetto Castle ActiveRecords. L'ho usato per un breve periodo di tempo per aumentare del nuovo codice per un progetto legacy. Usa NHibernate e funziona sul pattern di registrazione attivo (sorprendente dato il nome che conosco). Non ho provato, ma presumo che una volta che l'hai usato, se senti il ​​bisogno di passare direttamente al supporto di NHibernate, non sarebbe troppo farlo per una parte o per tutto il tuo progetto.


0

Come hai scritto "per una persona che non ha utilizzato nessuno dei due", LINQ to SQL è facile da usare, quindi chiunque può usarlo facilmente Supporta anche le procedure, il che aiuta la maggior parte del tempo. Supponi di voler ottenere dati da più di una tabella, quindi scrivi una procedura e trascina quella procedura nel designer e creerà tutto per te, Supponiamo che il nome della tua procedura sia "CUSTOMER_ORDER_LINEITEM" che recupera il record da tutte queste tre tabelle quindi scrivi semplicemente

MyDataContext db = new MyDataContext();
List<CUSTOMER_ORDER_LINEITEMResult> records = db.CUSTOMER_ORDER_LINEITEM(pram1, param2 ...).ToList<CUSTOMER_ORDER_LINEITEMResult>();

puoi anche usare il tuo oggetto record nel ciclo foreach, che non è supportato da NHibernate

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.