NHibernate vs LINQ to SQL

117

Als jemand, der keine der beiden Technologien für reale Projekte verwendet hat, frage ich mich, ob jemand weiß, wie sich diese beiden ergänzen und wie sehr sich ihre Funktionen überschneiden.

Manu
quelle

Antworten:

113

LINQ to SQL zwingt Sie, das Muster "Tabelle pro Klasse" zu verwenden. Die Verwendung dieses Musters hat den Vorteil, dass es schnell und einfach zu implementieren ist und nur sehr wenig Aufwand erforderlich ist, um Ihre Domain basierend auf einer vorhandenen Datenbankstruktur zum Laufen zu bringen. Für einfache Anwendungen ist dies durchaus akzeptabel (und oft sogar vorzuziehen), aber für komplexere Anwendungen schlagen Entwickler häufig vor, stattdessen ein domänengesteuertes Entwurfsmuster zu verwenden (was NHibernate erleichtert).

Das Problem mit dem Muster "Tabelle pro Klasse" besteht darin, dass Ihre Datenbankstruktur einen direkten Einfluss auf Ihr Domain-Design hat. Angenommen, Sie haben eine Kundentabelle mit den folgenden Spalten, in der die primären Adressinformationen eines Kunden gespeichert sind:

  • Adresse
  • Stadt
  • Zustand
  • Postleitzahl

Angenommen, Sie möchten auch Spalten für die Postanschrift des Kunden hinzufügen, damit Sie der Kundentabelle die folgenden Spalten hinzufügen:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

Bei Verwendung von LINQ to SQL verfügt das Kundenobjekt in Ihrer Domäne nun über Eigenschaften für jede dieser acht Spalten. Wenn Sie jedoch einem domänengesteuerten Entwurfsmuster folgen würden, hätten Sie wahrscheinlich eine Adressklasse erstellt und Ihre Kundenklasse zwei Adresseneigenschaften enthalten lassen, eine für die Postanschrift und eine für ihre aktuelle Adresse.

Das ist ein einfaches Beispiel, aber es zeigt, wie das Muster der Tabelle pro Klasse zu einer etwas stinkenden Domäne führen kann. Am Ende liegt es an Ihnen. Auch für einfache Apps, die nur grundlegende CRUD-Funktionen (Erstellen, Lesen, Aktualisieren, Löschen) benötigen, ist LINQ to SQL aufgrund der Einfachheit ideal. Aber ich persönlich benutze NHibernate gerne, weil es eine sauberere Domain ermöglicht.

Edit: @lomaxx - Ja, das Beispiel, das ich verwendet habe, war simpel und hätte optimiert werden können, um gut mit LINQ to SQL zu funktionieren. Ich wollte es so einfach wie möglich halten, um den Punkt nach Hause zu fahren. Der Punkt bleibt jedoch, dass es mehrere Szenarien gibt, in denen es eine schlechte Idee wäre, wenn Ihre Datenbankstruktur Ihre Domänenstruktur bestimmt, oder zumindest zu einem suboptimalen OO-Design führt.

Kevin Pang
quelle
4
Sie können die Implementierung Ihres Repositorys mit Linq To SQL codieren. Dies ist sehr praktisch.
Nicolas Dorier
1
Ich denke, es ist nicht ActiveRecord, selbst zugeordnete Klassen kapseln einen Teil der Infrastrukturlogik. ActiveRecord-Muster wäre, wenn Sie Customer.Save () haben könnten. L2S implementiert das Unit of Work-Muster mit der DataContext-Klasse wie Session in nHibernate, aber NH hat einen echten POCO-Ansatz.
Hrvoje Hudo
1
@kevin "LINQ to SQL verwendet das aktive Datensatzmuster" Das ist nicht korrekt. Es ist so, als würde man sagen, dass ADO.NET einen aktiven Datensatz verwendet oder NHibernate einen aktiven Datensatz verwendet. Sie sind alle Datenzugriffstechnologien und erzwingen kein bestimmtes Datenzugriffsmuster. Ich persönlich verwende gerne Linq-to-SQL mit dem Repository-Muster. Sie haben Recht, dass linq-to-sql keine komplexen Zuordnungen wie NHibernate unterstützt.
Liammclennan
1
Wie wäre es stattdessen mit einer Normalisierung Ihrer Datenbank und der Generierung Ihrer DAL durch Tools wie SQLMetal?
Alex
3
@CoffeeAddict Wenn die Impedanzfehlanpassung zu groß ist, ist Ihre Anwendung zu kompliziert, um LINQ to SQL zu verwenden, imo. Der Grund, warum mein Beispiel stinkt, ist, dass die Verwendung von LINQ to SQL zu 8 Eigenschaften im Gegensatz zu 2 führen würde und Ihre Fähigkeit einschränkt, beispielsweise Funktionen zu implementieren, die eine Adressklasse aufnehmen, oder Routinen für die Adressklasse zu implementieren, die Sie könnten tun, wenn Sie NHibernate verwendet hatten.
Kevin Pang
26

Zwei Punkte, die bisher übersehen wurden:

Auch die neue fließende Schnittstelle zu Nhibernate scheint es weniger schmerzhaft zu machen, die Zuordnung von Nhibernate zu konfigurieren. (Entfernen eines der Schmerzpunkte von Nhibernate)


Aktualisieren

Linq to Nhiberate ist in Nhiberate v3, das jetzt in Alpha ist, besser . Nhiberate v3 wird voraussichtlich gegen Ende dieses Jahres ausgeliefert.

Die Entity Frame Work ab .net 4 scheint ebenfalls eine echte Option zu sein.

Ian Ringrose
quelle
2
Linq to NHibernate befindet sich noch in einem sehr frühen Stadium. Es ist keine vollständige Implementierung und möglicherweise überhaupt nicht produktionsbereit.
Liammclennan
Die neue LinqConnect 2.0-Version bietet einige zusätzliche Funktionen, z. B. die Vererbungsunterstützung für Tabellen pro Typ, die PLINQ-Unterstützung und die Batch-Updates. ORM Designer (Devart Entity Developer) bietet jetzt Model First-Unterstützung und Mapping-Synchronisierungsfunktion. Weitere Details: devart.com/news/2010/dotconnects600.html
Devart
23

@ Kevin: Ich denke, das Problem mit dem Beispiel, das Sie präsentieren, ist, dass Sie ein schlechtes Datenbankdesign verwenden. Ich hätte gedacht, Sie würden eine Kundentabelle und eine Adresstabelle erstellen und die Tabellen normalisieren. Wenn Sie dies tun, können Sie Linq To SQL definitiv für das von Ihnen vorgeschlagene Szenario verwenden. Scott Guthrie hat eine großartige Reihe von Beiträgen zur Verwendung von Linq To SQL die ich Ihnen dringend empfehlen würde.

Ich glaube nicht, dass man sagen könnte, dass Linq und NHibernate sich ergänzen, da dies bedeuten würde, dass sie zusammen verwendet werden könnten, und obwohl dies möglich ist, ist es viel besser, wenn Sie sich für eines entscheiden und daran festhalten.

Mit NHibernate können Sie Ihre Datenbanktabellen auf sehr flexible Weise Ihren Domänenobjekten zuordnen. Außerdem können Sie HBL zum Abfragen der Datenbank verwenden.

Mit Linq to SQL können Sie auch Ihre Domänenobjekte der Datenbank zuordnen, verwenden jedoch die Linq-Abfragesyntax, um die Datenbank abzufragen

Der Hauptunterschied besteht darin, dass die Linq-Abfragesyntax beim Kompilieren vom Compiler überprüft wird, um sicherzustellen, dass Ihre Abfragen gültig sind.

Einige Dinge, die Sie bei linq beachten sollten, sind, dass es nur in .net 3.x verfügbar ist und nur in VS2008 unterstützt wird. NHibernate ist in 2.0 und 3.x sowie VS2005 erhältlich.

Einige Dinge, die Sie bei NHibernate beachten sollten, sind, dass weder Ihre Domänenobjekte noch die Zuordnungsdateien generiert werden. Sie müssen dies manuell tun. Linq kann
dies automatisch für Sie erledigen.

Lomaxx
quelle
15
Was ist, wenn Sie Code für eine ältere Datenbankstruktur schreiben, die Sie nicht ändern können, weil sie andere Apps unterstützt? Möchten Sie, dass Ihr Domänenmodell das schlechte Datenbankdesign erbt, oder möchten Sie ein umfangreiches Domänenmodell erstellen, das unabhängig von der Datenbankstruktur variieren kann?
Larry Foulkrod
7

Fluent NHibernate kann Ihre Mapping-Dateien basierend auf einfachen Konventionen generieren. Kein XML-Schreiben und stark getippt.

Ich habe kürzlich an einem Projekt gearbeitet, bei dem wir aus Leistungsgründen von Linq zu SQL zu NHibernate wechseln mussten. Insbesondere die Art und Weise, wie L2S die Objekte materialisiert, scheint langsamer zu sein als die von NHibernate, und das Änderungsmanagement ist ebenfalls recht langsam. Und es kann schwierig sein, das Änderungsmanagement für bestimmte Szenarien auszuschalten, in denen es nicht benötigt wird.

Wenn Sie Ihre vom DataContext getrennten Entitäten verwenden möchten, z. B. in WCF-Szenarien, haben Sie möglicherweise große Probleme, sie erneut mit dem DataContext zu verbinden, um die Änderungen zu aktualisieren. Ich hatte damit keine Probleme mit NHibernate.

Das, was ich von L2S vermissen werde, ist hauptsächlich die Codegenerierung, die die Beziehungen an beiden Enden der Entitäten auf dem neuesten Stand hält. Aber ich denke, es gibt einige Tools für NHibernate, um das auch zu tun ...

Asgerhallas
quelle
2
Nur für den Fall, dass andere Ihren Beitrag lesen und auch daran denken, ein Schiff zu springen - .ObjectTrackingEnabled = falseauf Ihrem DataContexthätten Sie Ihr Problem mit der Änderungsverfolgung gelöst. Solange Sie sich für das Muster der Arbeitseinheit entscheiden und keine DDD ausführen möchten, liefert Linq-to-SQL wirklich.
Mattmc3
" Wir mussten aus Leistungsgründen von Linq zu SQL zu NHibernate wechseln. " - Nachdem ich einige Jahre lang [fließend, nicht weniger] NHibernate verwendet habe, fühle ich mich für Sie. Ich denke, wir haben meistens geschummelt und natives SQL für echte Leistungsdruckpunkte geschrieben. Es wäre interessant, ein Update (sechs Jahre später ...) darüber zu hören, wie Ihre Migration verlaufen ist und ob es sich gelohnt hat.
Ruffin
5

Können Sie klarstellen, was Sie unter "LINQ" verstehen?

LINQ ist keine Datenzugriffstechnologie, sondern nur eine Sprachfunktion, die das Abfragen als natives Konstrukt unterstützt. Es kann jedes Objektmodell abfragen, das bestimmte Schnittstellen unterstützt (z. B. IQueryable).

Viele Leute bezeichnen LINQ To SQL als LINQ, aber das ist überhaupt nicht richtig. Microsoft hat gerade LINQ To Entities mit .NET 3.5 SP1 veröffentlicht. Darüber hinaus verfügt NHibernate über eine LINQ-Schnittstelle, sodass Sie LINQ und NHibernate verwenden können, um auf Ihre Daten zuzugreifen.

Jon Galloway
quelle
2

Mit LINQ gehe ich davon aus, dass Sie LINQ zu SQL meinen, da mit LINQ an sich keine Datenbank "los" ist. Es ist nur eine Abfragesprache, die eine Menge Syntac-Zucker enthält, damit sie SQL-artig aussieht.

In den grundlegenden Beispielen scheinen sowohl NHibernate als auch LINQ to SQL das gleiche Problem zu lösen. Sobald Sie bestanden haben, werden Sie schnell feststellen, dass NHibernate viele Funktionen unterstützt, mit denen Sie wirklich umfangreiche Domänenmodelle erstellen können. Es gibt auch ein LINQ to NHibernate-Projekt, mit dem Sie LINQ verwenden können, um NHibernate auf die gleiche Weise abzufragen, wie Sie LINQ to SQL verwenden würden.

Ryan Rinaldi
quelle
1

Lassen Sie uns zunächst zwei verschiedene Dinge trennen: Die Datenbankmodellierung befasst sich mit den Daten, während sich die Objektmodellierung mit Entitäten und Beziehungen befasst.

Der Vorteil von Linq-to-SQL besteht darin, dass Klassen schnell aus dem Datenbankschema generiert werden, damit sie als aktive Datensatzobjekte verwendet werden können (siehe Definition des Entwurfsmusters für aktive Datensätze).

Der Vorteil von NHibernate besteht darin, Flexibilität zwischen Ihrer Objektmodellierung und der Datenbankmodellierung zu ermöglichen. Die Datenbank kann so modelliert werden, dass sie Ihre Daten am besten widerspiegelt, beispielsweise unter Berücksichtigung der Leistung. Während Ihre Objektmodellierung die Elemente der Geschäftsregel mithilfe eines Ansatzes wie Domain-Driven-Design am besten widerspiegelt. (siehe Kevin Pang Kommentar)

Bei älteren Datenbanken mit schlechten Modellierungs- und / oder Namenskonventionen spiegelt Linq-to-SQL diese unerwünschten Strukturen und Namen für Ihre Klassen wider. NHibernate kann dieses Durcheinander jedoch mit Daten-Mappern verbergen.

In Greenfield-Projekten, in denen Datenbanken eine gute Benennung und eine geringe Komplexität aufweisen, kann Linq-to-SQL eine gute Wahl sein.

Sie können Fluent NHibernate jedoch mit automatischen Zuordnungen für denselben Zweck mit Zuordnung als Konvention verwenden. In diesem Fall machen Sie sich keine Gedanken über Datenzuordnungen mit XML oder C # und lassen NHibernate das Datenbankschema aus Ihren Entitäten basierend auf einer Konvention generieren, die Sie anpassen können.

Andererseits ist die Lernkurve von Linq-to-SQL kleiner als die von NHibernate.

Humberto
quelle
0

Oder Sie können das Castle ActiveRecords-Projekt verwenden. Ich habe das für kurze Zeit verwendet, um neuen Code für ein Legacy-Projekt hochzufahren. Es verwendet NHibernate und arbeitet mit dem aktiven Aufzeichnungsmuster (überraschend angesichts seines Namens, den ich kenne). Ich habe es nicht versucht, aber ich gehe davon aus, dass es nicht zu viel wäre, dies für einen Teil oder das gesamte Projekt zu tun, wenn Sie es einmal verwendet haben und direkt auf den NHibernate-Support zurückgreifen müssen.


quelle
0

Wie Sie geschrieben haben "für eine Person, die keine von ihnen verwendet hat", ist LINQ to SQL einfach zu verwenden, so dass jeder es leicht verwenden kann. Es unterstützt auch Prozeduren, was die meiste Zeit hilft. Angenommen, Sie möchten Daten aus mehr als einer Tabelle abrufen, dann schreiben Sie eine Prozedur und ziehen Sie diese Prozedur in den Designer. Dadurch wird alles für Sie erstellt. Angenommen, Ihr Prozedurname lautet "CUSTOMER_ORDER_LINEITEM". Sie rufen den Datensatz aus all diesen drei Tabellen ab und schreiben dann einfach

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

Sie können Ihr Datensatzobjekt auch in einer foreach-Schleife verwenden, die von NHibernate nicht unterstützt wird

Ali Adravi
quelle