NHibernate vs LINQ to SQL

作为一个没有在实际项目中使用过这两种技术的人,我想知道是否有人知道这两种技术如何互补以及它们的功能有多重叠?

34666 次浏览

你能解释一下“ LINQ”是什么意思吗?

LINQ 不是一种数据访问技术,它只是一种语言特性,支持作为本地构造的查询。它可以查询任何支持特定接口的对象模型(例如 IQueryable)。

许多人将 LINQToSQL 称为 LINQ,但这并不完全正确。微软刚刚发布了。NET 3.5 SP1.另外,NHibernate 有一个 LINQ 接口,因此您可以使用 LINQ 和 NHibernate 来获取数据。

通过 LINQ,我假设您指的是 LINQ 到 SQL,因为 LINQ 本身没有与其相关的数据库“正在进行”。它只是一种查询语言,有大量的语法糖使它看起来像 SQL。

在最基本的例子中,NHibernate 和 LINQtoSQL 似乎都在解决同一个问题。一旦你通过了,你很快就会意识到 NHibernate 支持许多特性,允许你创建真正丰富的领域模型。还有一个 LINQ to NHibernate 项目,它允许您使用 LINQ 来查询 NHibernate,其方式与使用 LINQ to SQL 非常相似。

LINQtoSQL 强制您使用每个类的表模式。使用这种模式的好处在于,它可以快速、容易地实现,而且基于现有的数据库结构运行域只需要很少的努力。对于简单的应用程序,这是完全可以接受的(有时甚至更好) ,但对于更复杂的应用程序,开发人员通常会建议使用 领域驱动设计领域驱动设计模式(这是 NHibernate 所促进的)。

每类表模式的问题在于数据库结构对域设计有直接影响。例如,假设您有一个“客户”表,其中包含以下列,用于保存客户的主要地址信息:

  • 街道地址
  • 城市
  • 国务院
  • 什么都没有

现在,假设您还想为客户的邮件地址添加列,那么您可以将以下列添加到 Customer 表中:

  • 邮递街地址
  • 邮陵市
  • MailingState
  • 邮编

使用 LINQtoSQL,您域中的 Customer 对象现在将具有这八列中每一列的属性。但是如果您遵循域驱动的设计模式,那么您可能已经创建了一个 Address 类,并且让 Customer 类保存了两个 Address 属性,一个用于邮件地址,另一个用于它们的当前地址。

这是一个简单的示例,但它演示了每个类的表模式如何导致一个有点臭味的域。最终,还是取决于你。同样,对于只需要基本 CRUD (创建、读取、更新、删除)功能的简单应用程序,LINQtoSQL 因其简单性而非常理想。但就我个人而言,我喜欢使用 NHibernate,因为它有助于创建一个更清晰的域。

编辑:@lomaxx-是的,我使用的示例过于简单,本可以进行优化,以便与 LINQ to SQL 协同工作。我希望尽可能保持最基本的原则,以便把重点讲清楚。重点仍然是,有几种情况下,让您的数据库结构决定您的域结构将是一个坏主意,或者至少导致次优面向对象设计。

或者您可以使用 Castle ActiveRecords 项目。我已经使用它很短的时间来为遗留项目增加一些新代码。它使用 NHibernate 并在活动记录模式上工作(考虑到它的名字,我很惊讶)。我还没有尝试过,但是我假设一旦你使用了它,如果你觉得需要直接使用 NHibernate 支持,那么对于你的项目的部分或全部来说这样做不会太过分。

@ Kevin: 我认为你展示的这个例子的问题在于你使用的数据库设计很差。我认为您应该创建一个客户表和一个地址表,并对表进行规范化。如果您这样做了,那么您完全可以使用 LinqToSQL 来实现您所建议的场景。斯科特 · 格思里有一个 关于使用 Linq To SQL 的一系列文章我强烈建议你去查查。

I don't think you could say Linq and NHibernate complement each other as that would imply that they could be used together, and whilst this is possible, you're much better off choosing one and sticking to it.

NHibernate 允许您以高度灵活的方式将数据库表映射到域对象。它还允许您使用 HBL 来查询数据库。

Linq to SQL 还允许您将域对象映射到数据库,但是它使用 Linq 查询语法来查询数据库

这里的主要区别是 Linq 查询语法是 编译器在编译时检查以确保查询有效。

Some things to be aware of with linq is that it's only available in .net 3.x and is only supported in VS2008. NHibernate is available in 2.0 and 3.x as well as VS2005.

使用 NHibernate 需要注意的一些事情是,它不生成域对象,也不生成映射文件。你需要手动操作。Linq 可以
do this automatically for you.

迄今为止,有两点被忽略了:

  • LINQtoSQL 不适用于 Oracle or any database apart from SqlServer. 然而,第三方确实为 Oracle 提供了更好的支持,例如。一个 href = “ http://www.devArt.com/dotConnect/oracle/”rel = “ noReferrer”> devArt 的 dotConnect ,一个 href = “ http://www.Mindscape. co.nz/products/LightSpeed/”rel = “ noReferrer”> Mindscape 的 LightSpeed 和一个 href = “一个 href =”Http://www.alinq.org/翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳。(我个人对此没有任何经验)

  • Linq to NHibernate 允许您使用 Linq 和一个 Nhiberate,所以它可能 remove a reason not to use.

Also the new 连接 Nhibernate 的流畅界面 seems to make it less painful to configure Nhibernate’s mapping. (Removing one of the pain points of Nhibernate)


更新

Linq to Nhiberate 在 Nhiberate v3更好,现在在 abc 0。看起来 Nhiberate V3可能会在今年年底发货。

从.net4开始,实体框架工作也开始看起来像是一个真正的选择。

流畅的 NHibernate 可以基于简单的约定生成映射文件。

我最近参与了一个项目,出于性能方面的原因,我们需要从 Linq 转换到 SQL,再转换到 NHibernate。尤其是 L2S 实现对象的方式似乎比 NHibernate 的方式慢,而且变更管理也相当慢。对于不需要变更管理的特定场景,很难关闭变更管理。

如果您打算使用与 DataContext 断开连接的实体(例如在 WCF 场景中) ,那么在将它们再次连接到 DataContext 以更新更改时可能会遇到很多麻烦。我对 NHibernate 没有异议。

在 L2S 中,我最怀念的是能够保持实体两端关系最新的代码生成。但是我想 NHibernate 也有一些工具可以做到这一点。

正如你写的“对于一个人谁没有使用他们中的任何一个” LINQtoSQL 很容易使用,所以任何人都可以很容易地使用它 它还支持程序,这在大多数情况下是有帮助的。 假设您想从多个表中获取数据,然后编写一个过程并将该过程拖到设计器,它将为您创建所有内容, 假设您的过程名为“ CUSTOMER _ ORDER _ LINEITEM”,它从所有这三个表中获取记录,然后只需编写

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

也可以在 foreach 循环中使用 record 对象,这是 NHibernate 不支持的

首先让我们分开两件不同的事情: Database modeling is concerned about the data while object modeling is concerned about entities and relationships.

Linq-to-SQL advantage is to quickly generate classes out of database schema so that they can be used as active record objects (see active record design pattern definition).

NHibernate 的优势在于允许对象建模和数据库建模之间的灵活性。数据库的建模可以最好地反映您的数据,例如考虑到性能。虽然您的对象建模将最好地反映业务规则的元素,使用领域驱动设计(Domain-Driven-Design)等方法。(见彭凯文评论)

对于建模和/或命名约定较差的遗留数据库,Linq-to-SQL 将把这些不需要的结构和名称反映到类中。然而,NHibernate 可以通过数据映射器隐藏这种混乱。

在数据库具有良好命名和低复杂性的绿地项目中,Linq-to-SQL 可能是一个很好的选择。

然而,您可以将 具有自动映射的流畅 NHibernate用于与映射相同的目的,作为约定。在这种情况下,您不必担心使用 XML 或 C # 的任何数据映射器,而是让 NHibernate 根据您可以自定义的约定从您的实体生成数据库模式。

On the other hand learning curve of Linq-to-SQL is smaller then NHibernate.