NHibernate vs LINQ to SQL


117

En tant que personne qui n'a utilisé aucune de ces technologies sur des projets du monde réel, je me demande si quelqu'un sait comment ces deux technologies se complètent et à quel point leurs fonctionnalités se chevauchent.

Réponses:


113

LINQ to SQL vous oblige à utiliser le modèle table par classe. Les avantages de l'utilisation de ce modèle sont qu'il est rapide et facile à mettre en œuvre et qu'il ne faut que très peu d'efforts pour faire fonctionner votre domaine sur la base d'une structure de base de données existante. Pour les applications simples, c'est parfaitement acceptable (et souvent même préférable), mais pour les applications plus complexes, les développeurs suggéreront souvent d'utiliser une conception axée sur le domaine. modèle de la place (ce que NHibernate facilite).

Le problème avec le modèle table par classe est que la structure de votre base de données a une influence directe sur la conception de votre domaine. Par exemple, supposons que vous ayez une table Clients avec les colonnes suivantes pour contenir les informations d'adresse principale d'un client:

  • Adresse de rue
  • Ville
  • Etat
  • Zip *: français

Maintenant, supposons que vous souhaitiez également ajouter des colonnes pour l'adresse postale du client afin d'ajouter les colonnes suivantes à la table Clients:

  • MailingStreetAddress
  • MailingVille
  • MailingState
  • MailingZip

En utilisant LINQ to SQL, l'objet Customer de votre domaine aurait désormais des propriétés pour chacune de ces huit colonnes. Mais si vous suiviez un modèle de conception piloté par domaine, vous auriez probablement créé une classe Address et votre classe Customer détenait deux propriétés Address, une pour l'adresse postale et une pour leur adresse actuelle.

C'est un exemple simple, mais il montre comment le modèle table par classe peut conduire à un domaine un peu malodorant. En fin de compte, c'est à vous. Encore une fois, pour les applications simples qui n'ont besoin que de la fonctionnalité CRUD de base (créer, lire, mettre à jour, supprimer), LINQ to SQL est idéal en raison de sa simplicité. Mais personnellement, j'aime utiliser NHibernate car il facilite un domaine plus propre.

Edit: @lomaxx - Oui, l'exemple que j'ai utilisé était simpliste et aurait pu être optimisé pour bien fonctionner avec LINQ to SQL. Je voulais le garder aussi basique que possible pour faire ressortir le point. Il n'en reste pas moins qu'il existe plusieurs scénarios dans lesquels le fait de déterminer la structure de votre domaine par la structure de votre base de données serait une mauvaise idée, ou au moins conduirait à une conception OO sous-optimale.


4
Vous pouvez coder l'implémentation de votre référentiel en utilisant Linq To SQL, c'est très pratique.
Nicolas Dorier

1
Je pense que ce n'est pas ActiveRecord, même les classes mappées encapsulent une partie de la logique de l'infrastructure. Le modèle ActiveRecord serait si vous pouviez avoir Customer.Save (). L2S implémente le modèle Unit of Work avec la classe DataContext, comme Session dans nHibernate, mais NH a une vraie approche POCO.
Hrvoje Hudo

1
@kevin "LINQ to SQL utilise le modèle d'enregistrement actif" Ce n'est pas correct. C'est comme dire qu'ADO.NET utilise un enregistrement actif ou que NHibernate utilise un enregistrement actif. Ce sont toutes des technologies d'accès aux données et n'appliquent aucun modèle d'accès aux données particulier. J'aime personnellement utiliser linq-to-sql avec le modèle de référentiel. Vous avez raison de dire que linq-to-sql ne prend pas en charge les mappages complexes comme le fait NHibernate.
liammclennan

1
Qu'en est-il à la place de normaliser votre base de données et de laisser votre DAL être généré par des outils tels que SQLMetal?
Alex

3
@CoffeeAddict Lorsque la discordance d'impédance est trop lourde à supporter, c'est à ce moment que votre application est trop compliquée pour utiliser LINQ to SQL, imo. La raison pour laquelle mon exemple est malodorant est que l'utilisation de LINQ to SQL entraînerait 8 propriétés au lieu de 2 et restreindrait votre capacité à faire des choses comme implémenter des fonctions qui prennent dans une classe Address ou implémenter des routines sur la classe Address que vous seriez en mesure de faites si vous aviez utilisé NHibernate.
Kevin Pang

26

Deux points qui ont été manqués jusqu'à présent:

  • LINQ to SQL ne fonctionne pas avec Oracle ou toute autre base de données en dehors de SqlServer. Cependant 3e parties ne offrent un meilleur soutien pour Oracle, par exemple dotConnect de DevArt , DbLinq , LightSpeed de Mindscape et ALinq . (Je n'ai aucune expérience personnelle avec ces derniers)

  • Linq to NHibernate vous permet d'utiliser Linq avec un Nhiberate, il peut donc supprimer une raison de ne pas l'utiliser.

De plus, la nouvelle interface fluide de Nhibernate semble rendre la configuration de la cartographie de Nhibernate moins compliquée. (Suppression de l'un des points douloureux de Nhibernate)


Mettre à jour

Linq to Nhiberate est meilleur dans Nhiberate v3 qui est maintenant en alpha . On dirait que Nhiberate v3 pourrait être livré vers la fin de cette année.

L' Entity Frame Work à partir de .net 4 commence également à ressembler à une véritable option.


2
Linq to NHibernate est encore à un stade très précoce. Il ne s'agit pas d'une implémentation complète et, sans doute, n'est pas du tout prête pour une utilisation en production.
liammclennan

La nouvelle version de LinqConnect 2.0 introduit des fonctionnalités supplémentaires pour plus de commodité, comme la prise en charge de l'héritage de table par type, la prise en charge de PLINQ et la fonctionnalité de mises à jour par lots. ORM Designer (Devart Entity Developer) prend désormais en charge Model First et la fonction de synchronisation de mappage. Plus de détails: devart.com/news/2010/dotconnects600.html
Devart

23

@Kevin: Je pense que le problème avec l'exemple que vous présentez est que vous utilisez une mauvaise conception de base de données. J'aurais pensé que vous créeriez une table client et une table d'adresses et que vous normaliseriez les tables. Si vous faites cela, vous pouvez certainement utiliser Linq To SQL pour le scénario que vous suggérez. Scott Guthrie a une grande série d'articles sur l'utilisation de Linq To SQL que je vous suggère fortement de consulter.

Je ne pense pas que vous puissiez dire que Linq et NHibernate se complètent car cela impliquerait qu'ils pourraient être utilisés ensemble, et bien que cela soit possible, vous feriez bien mieux d'en choisir un et de vous y tenir.

NHibernate vous permet de mapper vos tables de base de données à vos objets de domaine de manière très flexible. Il vous permet également d'utiliser HBL pour interroger la base de données.

Linq to SQL vous permet également de mapper vos objets de domaine à la base de données, mais il utilise la syntaxe de requête Linq pour interroger la base de données

La principale différence ici est que la syntaxe de la requête Linq est vérifiée au moment de la compilation par le compilateur pour s'assurer que vos requêtes sont valides.

Certaines choses à savoir avec linq sont qu'il n'est disponible que dans .net 3.x et n'est pris en charge que dans VS2008. NHibernate est disponible en 2.0 et 3.x ainsi qu'en VS2005.

Certaines choses à savoir avec NHibernate sont qu'il ne génère pas vos objets de domaine, ni ne génère les fichiers de mappage. Vous devez le faire manuellement. Linq peut le
faire automatiquement pour vous.


15
Que faire si vous écrivez du code sur une structure de base de données héritée que vous ne pouvez pas modifier car elle prend en charge d'autres applications. Voulez-vous que votre modèle de domaine hérite de la mauvaise conception de la base de données ou souhaitez-vous créer un modèle de domaine riche qui peut varier indépendamment de la structure de la base de données?
Larry Foulkrod

7

Fluent NHibernate peut générer vos fichiers de cartographie sur la base de conventions simples. Aucune écriture XML et fortement typé.

J'ai récemment travaillé sur un projet, dans lequel nous devions passer de Linq à SQL à NHibernate pour des raisons de performances. Surtout la manière de matérialiser les objets par L2S semble plus lente que celle de NHibernate et la gestion du changement est également assez lente. Et il peut être difficile de désactiver la gestion du changement pour des scénarios spécifiques où elle n'est pas nécessaire.

Si vous envisagez d'utiliser vos entités déconnectées du DataContext - dans les scénarios WCF par exemple - vous risquez de rencontrer de nombreux problèmes pour les connecter à nouveau au DataContext pour mettre à jour les modifications. Je n'ai eu aucun problème avec cela avec NHibernate.

Ce qui me manquera dans L2S, c'est surtout la génération de code qui maintient les relations à jour aux deux extrémités des entités. Mais je suppose qu'il existe des outils pour NHibernate pour le faire aussi ...


2
Juste au cas où d'autres liraient votre message et songeraient également à sauter le navire .ObjectTrackingEnabled = false, vous DataContextauriez résolu votre problème de suivi des modifications. Tant que vous adhérez au modèle d'unité de travail et que vous ne cherchez pas à faire du DDD, Linq-to-SQL est vraiment efficace.
mattmc3

" nous devions passer de Linq à SQL à NHibernate pour des raisons de performances " - Ayant utilisé [Fluent, pas moins] NHibernate pendant quelques années, je ressens pour vous. Je pense que nous avons surtout triché et avons fini par écrire du SQL natif pour de réels points de pression sur les performances. Ce serait intéressant d'entendre une mise à jour (six ans plus tard ...) sur le déroulement de votre migration et si cela en valait la peine.
ruffin

5

Pouvez-vous clarifier ce que vous entendez par "LINQ"?

LINQ n'est pas une technologie d'accès aux données, c'est juste une fonctionnalité de langage qui prend en charge les requêtes en tant que construction native. Il peut interroger n'importe quel modèle d'objet prenant en charge des interfaces spécifiques (par exemple IQueryable).

Beaucoup de gens se réfèrent à LINQ To SQL comme LINQ, mais ce n'est pas du tout correct. Microsoft vient de publier LINQ To Entities avec .NET 3.5 SP1. De plus, NHibernate dispose d'une interface LINQ, vous pouvez donc utiliser LINQ et NHibernate pour accéder à vos données.


2

Par LINQ, je suppose que vous entendez LINQ to SQL parce que LINQ, par lui-même, n'a pas de base de données "en cours" qui lui est associée. C'est juste un langage de requête qui a une charge de sucre syntacique pour lui donner un aspect SQL-ish.

Dans les exemples les plus basiques, NHibernate et LINQ to SQL semblent tous deux résoudre le même problème. Une fois que vous avez réussi, vous vous rendez vite compte que NHibernate prend en charge de nombreuses fonctionnalités qui vous permettent de créer des modèles de domaine vraiment riches. Il existe également un projet LINQ to NHibernate qui vous permet d'utiliser LINQ pour interroger NHibernate de la même manière que vous utiliseriez LINQ to SQL.


1

Commençons par séparer deux choses différentes: la modélisation de base de données concerne les données tandis que la modélisation d'objets concerne les entités et les relations.

L'avantage de Linq-to-SQL est de générer rapidement des classes à partir du schéma de base de données afin qu'elles puissent être utilisées comme objets d'enregistrement actifs (voir la définition du modèle de conception d'enregistrement actif).

L'avantage NHibernate est de permettre une flexibilité entre votre modélisation d'objets et la modélisation de base de données. La base de données peut être modélisée pour refléter au mieux vos données en tenant compte des performances par exemple. Alors que votre modélisation d'objets reflètera le mieux les éléments de la règle métier en utilisant une approche telle que Domain-Driven-Design. (voir le commentaire de Kevin Pang)

Avec des bases de données héritées avec de mauvaises conventions de modélisation et / ou de dénomination, Linq-to-SQL reflétera ces structures et noms indésirables dans vos classes. Cependant NHibernate peut cacher ce désordre avec les mappeurs de données.

Dans les nouveaux projets où les bases de données ont une bonne dénomination et une faible complexité, Linq-to-SQL peut être un bon choix.

Cependant, vous pouvez utiliser Fluent NHibernate avec des mappages automatiques dans ce même but avec le mappage comme convention. Dans ce cas, vous ne vous souciez pas des mappeurs de données avec XML ou C # et laissez NHibernate générer le schéma de base de données à partir de vos entités selon une convention que vous pouvez personnaliser.

D'autre part, la courbe d'apprentissage de Linq-to-SQL est plus petite que NHibernate.


0

Ou vous pouvez utiliser le projet Castle ActiveRecords. J'utilise cela depuis peu de temps pour créer un nouveau code pour un projet hérité. Il utilise NHibernate et fonctionne sur le modèle d'enregistrement actif (surprenant étant donné son nom que je connais). Je n'ai pas essayé, mais je suppose qu'une fois que vous l'avez utilisé, si vous ressentez le besoin de passer directement au support NHibernate, ce ne serait pas trop de le faire pour tout ou partie de votre projet.


0

Comme vous l'avez écrit "pour une personne qui n'a utilisé aucun des deux" LINQ to SQL est facile à utiliser et tout le monde peut l'utiliser facilement. Il prend également en charge les procédures, ce qui aide la plupart du temps. Supposons que vous souhaitiez obtenir des données de plus d'une table, puis écrivez une procédure et faites glisser cette procédure vers le concepteur et elle créera tout pour vous, Supposons que le nom de votre procédure soit "CUSTOMER_ORDER_LINEITEM" qui récupère l'enregistrement de ces trois tables puis écrivez simplement

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

vous pouvez également utiliser votre objet records dans la boucle foreach, ce qui n'est pas pris en charge par NHibernate

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.