NHibernate与LINQ to SQL

作为一个在现实世界的项目中没有使用任何一种技术的人,我想知道有没有人知道这两者是如何相互补充的,以及它们的function有多重叠?

LINQ to SQL迫使您使用每类表格模式。 使用这种模式的好处是实现起来快速简单,只需要很less的努力就可以基于现有的数据库结构来运行域。 对于简单的应用程序来说,这是完全可以接受的(通常甚至更可取),但是对于更复杂的应用程序,开发人员通常会build议使用域驱动的devise模式(这正是NHibernate所促进的)。

每类表格模式的问题是您的数据库结构对您的域devise有直接的影响。 例如,假设您的Customers表中包含以下列以保存客户的主要地址信息:

  • 街道地址
  • 压缩

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

  • MailingStreetAddress
  • MailingCity
  • MailingState
  • MailingZip

使用LINQ to SQL,您的域中的Customer对象现在将具有这八列中的每一列的属性。 但是,如果您遵循的是域驱动的devise模式,那么您可能会创build一个Address类,并让您的Customer类拥有两个Address属性,一个用于邮寄地址,一个用于当前地址。

这是一个简单的例子,但是它演示了每类表格模式如何导致一个有点臭的领域。 最后,这取决于你。 同样,对于简单的应用程序,只需要基本的CRUD(创build,读取,更新,删除)function,因为简单,LINQ to SQL是理想的。 但我个人喜欢使用NHibernate,因为它有利于一个更清洁的域名。

编辑:@lomaxx – 是的,我使用的例子是简单的,可以被优化,以适应与LINQ to SQL。 我想尽可能保持基本的原则。 问题的关键在于,有几种情况是你的数据库结构决定了你的域结构是一个坏主意,或者至less会导致OOdevise不太理想。

到目前为止已经错过了两点:

  • 除了SqlServer以外,LINQ to SQL不适用于Oracle或任何数据库。 然而第三方确实提供了对Oracle的更好的支持,例如devArt的dotConnect , DbLinq , Mindscape的LightSpeed和ALinq 。 (我没有任何亲身经历)

  • Linq到NHibernate可以让你用一个Nhiberate来使用Linq,所以它可能会删除一个不使用的理由。

另外Nhibernate的新stream畅界面似乎使configurationNhibernate的映射变得不那么痛苦。 (去除Nhibernate的痛点之一)


更新

Linq在Nhiberate v3中是更好的,现在是alpha 。 看起来Nhiberate v3可能会在今年年底发货。

entity framework作为.NET 4也开始看起来像一个真正的select。

@Kevin:我认为你提出的例子的问题是你正在使用一个糟糕的数据库devise。 我原以为你会创build一个客户表和一个地址表,并规范化表。 如果你这样做,你可以明确地使用Linq To SQL来build议你的场景。 Scott Guthrie有很多关于使用Linq To SQL的post ,我强烈build议你检查一下。

我不认为你可以说Linq和NHibernate相互补充,因为这意味着他们可以一起使用,虽然这是可能的,但你select一个坚持下去更好。

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

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

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

Linq需要注意的一点是,它只能在.net 3.x中使用,并且只在VS2008中受支持。 NHibernate可以在2.0和3.x以及VS2005中使用。

有些事情要注意与NHibernate的是,它不会生成您的域对象,也不会生成映射文件。 您需要手动执行此操作。 Linq可以
自动为你做。

stream利的NHibernate可以根据简单的约定生成映射文件。 没有XML写入和强types。

我最近在一个项目上工作,出于性能方面的考虑,我们需要从Linq To SQL更改为NHibernate。 特别是L2S实现对象的方式似乎比NHibernate的同样慢,变化pipe理也很慢。 在不需要的情况下,可能很难将变更pipe理closures。

如果要使用与DataContext断开连接的实体(例如在WCF场景中),那么将它们连接到DataContext以更新更改可能会遇到很多问题。 我用NHibernate没有问题。

我会从L2S中遗漏的东西大部分是代码生成,它使实体两端的关系保持最新。 但我想有一些NHibernate的工具也可以做到这一点…

你能澄清你的意思是“LINQ”吗?

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

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

通过LINQ,我假定你的意思是LINQ to SQL,因为LINQ本身并没有与之关联的数据库。 这只是一个查询语言,它有一个syntac糖的船载,使它看起来SQL-ish。

在基本的例子中,NHibernate和LINQ to SQL似乎都解决了同样的问题。 一旦你通过了,你很快就会意识到NHibernate支持许多function,允许你创build真正丰富的域模型。 还有一个LINQ to NHibernate项目,允许你使用LINQ查询NHibernate,就像你使用LINQ to SQL一样。

首先让我们分离两个不同的东西:数据库build模关注数据,而对象build模则关注实体和关系。

Linq-to-SQL的优势在于快速生成数据库模式中的类,以便将它们用作活动logging对象(请参阅活动loggingdevise模式定义)。

NHibernate的优势在于允许对象build模和数据库build模之间的灵活性。 数据库可以build模,以最好地反映您考虑到性能的数据。 虽然您的对象build模将最好地反映业务规则的要素,使用一种方法,如域驱动devise。 (见Kevin Pang评论)

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

在数据库命名好,复杂度低的新build项目中,Linq-to-SQL可以是不错的select。

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

另一方面Linq-to-SQL的学习曲线比NHibernate小。

或者你可以使用Castle ActiveRecords项目。 我一直在使用它来为传统项目增加一些新的代码。 它使用NHibernate和工作在活动的logging模式(令人惊讶,因为我知道它的名字)。 我还没有尝试过,但是我认为一旦你使用了它,如果你觉得需要直接删除到NHibernate的支持,那么对于部分或者全部的项目来说不会太多。

正如你所写的“对于一个没有使用过它们的人”,LINQ to SQL很容易使用,所以任何人都可以轻松使用它也支持程序,这在大多数情况下都有帮助。 假设你想从多个表中获取数据,然后编写一个过程并将该过程拖到devise器上,它会为你创build一切,假设你的过程名是“CUSTOMER_ORDER_LINEITEM”,它从所有这三个表中获取logging,然后只写

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

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