NHibernate против LINQ to SQL

117

Как человек, который не использовал ни одну из технологий в реальных проектах, мне интересно, знает ли кто-нибудь, как эти две технологии дополняют друг друга и насколько их функции перекрываются?

Manu
источник

Ответы:

113

LINQ to SQL заставляет вас использовать шаблон «таблица для класса». Преимущества использования этого шаблона заключаются в том, что его быстро и легко реализовать, и требуется совсем немного усилий для запуска вашего домена на основе существующей структуры базы данных. Для простых приложений это вполне приемлемо (и часто даже предпочтительнее), но для более сложных приложений разработчики часто предлагают вместо этого использовать шаблон проектирования, управляемый доменом (что и облегчает NHibernate).

Проблема с шаблоном «таблица на класс» заключается в том, что структура вашей базы данных имеет прямое влияние на дизайн вашей предметной области. Например, предположим, что у вас есть таблица «Клиенты» со следующими столбцами для хранения информации об основном адресе клиента:

  • Адрес улицы
  • город
  • государство
  • застежка-молния

Теперь предположим, что вы хотите добавить столбцы для почтового адреса клиента, поэтому вы добавляете следующие столбцы в таблицу клиентов:

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

При использовании LINQ to SQL объект Customer в вашем домене теперь будет иметь свойства для каждого из этих восьми столбцов. Но если бы вы следовали шаблону проектирования, управляемому доменом, вы, вероятно, создали бы класс Address и ваш класс Customer содержал бы два свойства Address: одно для почтового адреса, а другое - для их текущего адреса.

Это простой пример, но он демонстрирует, как шаблон «таблица на класс» может привести к несколько неприятному запаху. В конце концов, решать только вам. Опять же, для простых приложений, которым просто необходимы базовые функции CRUD (создание, чтение, обновление, удаление), LINQ to SQL идеален из-за простоты. Но лично мне нравится использовать NHibernate, потому что он способствует более чистому домену.

Изменить: @lomaxx - Да, пример, который я использовал, был упрощенным и мог быть оптимизирован для хорошей работы с LINQ to SQL. Я хотел, чтобы это было как можно более простым, чтобы донести до сути суть. Однако суть в том, что существует несколько сценариев, в которых структура вашей базы данных, определяющая структуру домена, будет плохой идеей или, по крайней мере, приведет к неоптимальному объектно-ориентированному дизайну.

Кевин Панг
источник
4
Вы можете закодировать реализацию своего репозитория с помощью Linq To SQL, это очень удобно.
Николас Дориер
1
Я думаю, что это не ActiveRecord, даже сопоставленные классы инкапсулируют часть логики инфраструктуры. Шаблон ActiveRecord был бы, если бы у вас был Customer.Save (). L2S реализует шаблон Unit of Work с классом DataContext, как Session в nHibernate, но NH имеет реальный подход POCO.
Hrvoje Hudo
1
@kevin "LINQ to SQL использует шаблон активной записи" Это неверно. Это как сказать, что ADO.NET использует активную запись или NHibernate использует активную запись. Все они являются технологиями доступа к данным и не применяют какой-либо конкретный шаблон доступа к данным. Мне лично нравится использовать linq-to-sql с шаблоном репозитория. Вы правы, что linq-to-sql не поддерживает сложные сопоставления, как это делает NHibernate.
liammclennan
1
А как насчет нормализации базы данных и создания возможности создания DAL с помощью инструментов, например SQLMetal?
Alex
3
@CoffeeAddict Когда несоответствие импеданса слишком велико, это когда ваше приложение слишком сложно для использования LINQ to SQL, imo. Причина, по которой мой пример вонючий, заключается в том, что использование LINQ to SQL приведет к 8 свойствам, а не 2, и ограничит вашу способность делать такие вещи, как реализация функций, которые принимают класс Address, или реализуют подпрограммы в классе Address, которые вы могли бы использовать сделайте, если вы использовали NHibernate.
Кевин Панг,
26

Два момента, которые были упущены до сих пор:

  • LINQ to SQL не работает с Oracle или любой другой базой данных, кроме SqlServer. Однако сторонние производители предлагают лучшую поддержку Oracle, например dotConnect от devArt , DbLinq , LightSpeed ​​от Mindscape и ALinq . (У меня нет личного опыта с ними)

  • Linq to NHibernate позволяет использовать Linq с Nhiberate, поэтому он может устранить причину отказа от использования.

Кроме того, новый свободный интерфейс для Nhibernate, кажется, делает менее болезненным настройку отображения Nhibernate. (Удаление одной из болевых точек Nhibernate)


Обновить

Linq to Nhiberate лучше в Nhiberate v3, который сейчас находится в альфа- версии . Похоже, что Nhiberate v3 может выйти в продажу ближе к концу этого года.

Entity рамки работы от .net 4 также начинает выглядеть как реальный вариант.

Ян Рингроуз
источник
2
Linq для NHibernate все еще находится на очень ранней стадии. Это не полная реализация, и, возможно, она вообще не готова для промышленного использования.
liammclennan
В новом выпуске LinqConnect 2.0 для удобства представлены некоторые дополнительные функции, такие как поддержка наследования таблиц по типам, поддержка PLINQ и функция пакетного обновления. ORM Designer (Devart Entity Developer) теперь имеет поддержку Model First и функцию Mapping Synchronization. Подробнее: devart.com/news/2010/dotconnects600.html
Devart
23

@Kevin: Я думаю, что проблема с примером, который вы представляете, заключается в том, что вы используете плохой дизайн базы данных. Я бы подумал, что вы создадите таблицу клиентов и таблицу адресов и нормализуете таблицы. Если вы это сделаете, вы определенно можете использовать Linq To SQL для предлагаемого сценария. У Скотта Гатри есть отличная серия сообщений об использовании Linq To SQL, которые я настоятельно рекомендую вам проверить.

Я не думаю, что вы могли бы сказать, что Linq и NHibernate дополняют друг друга, поскольку это означало бы, что их можно использовать вместе, и хотя это возможно, вам гораздо лучше выбрать один и придерживаться его.

NHibernate позволяет очень гибко сопоставлять таблицы базы данных с объектами домена. Он также позволяет использовать HBL для запроса базы данных.

Linq to SQL также позволяет отображать объекты вашего домена в базе данных, однако он использует синтаксис запроса Linq для запроса базы данных.

Основное отличие здесь заключается в том, что синтаксис запроса Linq проверяется компилятором во время компиляции, чтобы убедиться, что ваши запросы действительны.

Что нужно знать о linq, так это то, что он доступен только в .net 3.x и поддерживается только в VS2008. NHibernate доступен в версиях 2.0 и 3.x, а также VS2005.

При использовании NHibernate следует помнить о том, что он не генерирует объекты вашего домена и не генерирует файлы сопоставления. Делать это нужно вручную. Linq может
сделать это автоматически.

lomaxx
источник
15
Что делать, если вы пишете код для устаревшей структуры базы данных, которую вы не можете изменить, поскольку она поддерживает другие приложения. Вы хотите, чтобы ваша модель предметной области унаследовала плохой дизайн базы данных или вы хотите создать богатую модель предметной области, которая может варьироваться независимо от структуры базы данных?
Ларри Фоулкрод,
7

Fluent NHibernate может генерировать ваши файлы сопоставления на основе простых соглашений. Нет XML-записи и строго типизирован.

Недавно я работал над проектом, в котором нам нужно было перейти с Linq на SQL на NHibernate по соображениям производительности. В частности, способ материализации объектов в L2S кажется медленнее, чем то же самое в NHibernate, и управление изменениями тоже довольно медленное. И может быть сложно отключить управление изменениями для определенных сценариев, где это не нужно.

Если вы собираетесь использовать свои сущности, отключенные от DataContext - например, в сценариях WCF - у вас могут возникнуть проблемы с повторным подключением их к DataContext для обновления изменений. У меня не было проблем с NHibernate.

В L2S мне будет не хватать в основном генерации кода, который поддерживает актуальность отношений на обоих концах сущностей. Но я предполагаю, что для NHibernate есть инструменты, позволяющие это сделать ...

asgerhallas
источник
2
На всякий случай, если другие прочитают ваш пост и тоже подумают о том, чтобы спрыгнуть с корабля - .ObjectTrackingEnabled = falseвы DataContextбы решили проблему отслеживания изменений. Если вы соглашаетесь с шаблоном единичной работы и не хотите выполнять DDD, Linq-to-SQL действительно работает.
mattmc3
« нам нужно было перейти с Linq на SQL на NHibernate по соображениям производительности » - я сочувствую вам, используя [Fluent, не меньше] NHibernate в течение нескольких лет. Я думаю, что мы в основном жульничали и в итоге написали собственный SQL для реальных проблем с производительностью. Было бы интересно услышать обновленную информацию (шесть лет спустя ...) о том, как прошла ваша миграция, и стоило ли оно того.
ruffin
5

Не могли бы вы пояснить, что вы имеете в виду под «LINQ»?

LINQ - это не технология доступа к данным, это просто языковая функция, которая поддерживает запросы в качестве собственной конструкции. Он может запрашивать любую объектную модель, которая поддерживает определенные интерфейсы (например, IQueryable).

Многие люди называют LINQ To SQL LINQ, но это совсем не правильно. Microsoft только что выпустила LINQ To Entities с .NET 3.5 SP1. Кроме того, NHibernate имеет интерфейс LINQ, поэтому вы можете использовать LINQ и NHibernate для доступа к своим данным.

Джон Гэллоуэй
источник
2

Под LINQ я предполагаю, что вы имеете в виду LINQ to SQL, потому что LINQ, сам по себе, не имеет связанных с базой данных. Это просто язык запросов, у которого есть масса синтаксического сахара, чтобы он выглядел в стиле SQL.

В самом простом из основных примеров NHibernate и LINQ to SQL, похоже, решают одну и ту же проблему. Как только вы пройдете, вы скоро поймете, что NHibernate поддерживает множество функций, которые позволяют создавать действительно богатые модели предметной области. Существует также проект LINQ to NHibernate, который позволяет вам использовать LINQ для запроса NHibernate почти так же, как вы использовали бы LINQ to SQL.

Райан Ринальди
источник
1

Сначала давайте разделим две разные вещи: моделирование баз данных касается данных, а моделирование объектов - сущностей и отношений.

Преимущество Linq-to-SQL заключается в быстром создании классов из схемы базы данных, чтобы их можно было использовать в качестве объектов активной записи (см. Определение шаблона проектирования активной записи).

Преимущество NHibernate заключается в обеспечении гибкости между моделированием объектов и моделированием базы данных. База данных может быть смоделирована так, чтобы наилучшим образом отражать ваши данные, например, с учетом производительности. Хотя ваше объектное моделирование будет лучше всего отражать элементы бизнес-правила, используя такой подход, как Domain-Driven-Design. (см. комментарий Кевина Пэна)

В устаревших базах данных с плохими соглашениями о моделировании и / или именовании Linq-to-SQL будет отражать эти нежелательные структуры и имена для ваших классов. Однако NHibernate может скрыть этот беспорядок с помощью преобразователей данных.

В новых проектах, где базы данных имеют хорошее именование и низкую сложность, Linq-to-SQL может быть хорошим выбором.

Однако вы можете использовать Fluent NHibernate с автоматическими сопоставлениями для той же цели с сопоставлением в качестве соглашения. В этом случае вам не нужно беспокоиться о каких-либо преобразователях данных с XML или C # и позволить NHibernate генерировать схему базы данных из ваших сущностей на основе соглашения, которое вы можете настроить.

С другой стороны, кривая обучения Linq-to-SQL меньше, чем NHibernate.

Умберто
источник
0

Или вы можете использовать проект Castle ActiveRecords. Я использовал это в течение короткого времени, чтобы набрать новый код для унаследованного проекта. Он использует NHibernate и работает с шаблоном активной записи (удивительно, учитывая его название, которое я знаю). Я не пробовал, но предполагаю, что после того, как вы его использовали, если вы почувствуете необходимость напрямую перейти к поддержке NHibernate, это не будет слишком много для части или всего вашего проекта.


источник
0

Как вы написали «для человека, который не использовал ни один из них», LINQ to SQL прост в использовании, поэтому его может легко использовать любой. Он также поддерживает процедуры, что помогает большую часть времени. Предположим, вы хотите получить данные из более чем одной таблицы, затем напишите процедуру и перетащите эту процедуру в конструктор, и он создаст все для вас. Предположим, ваше имя процедуры - «CUSTOMER_ORDER_LINEITEM», которое извлекает запись из всех этих трех таблиц, а затем просто напишите

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

вы также можете использовать объект записи в цикле foreach, который не поддерживается NHibernate

Али Адрави
источник