NHibernate与LINQ to SQL


117

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

Answers:


113

LINQ to SQL强制您使用每类表模式。使用此模式的好处在于,它实现起来快速简便,并且只需花费很少的精力就可以在现有数据库结构的基础上运行域。对于简单的应用程序,这是完全可以接受的(并且有时甚至更可取),但是对于更复杂的应用程序,开发人员通常会建议改用域驱动的设计模式(这是NHibernate所促进的)。

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

  • 街道地址
  • 压缩

现在,假设您也要为客户的邮寄地址添加列,以便在“客户”表中添加以下列:

  • MailingStreetAddress
  • 邮寄城市
  • 邮件状态
  • 邮递区号

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

这是一个简单的示例,但它演示了“按表创建表”模式如何导致有些臭味的域。最后,取决于您。同样,对于仅需要基本CRUD(创建,读取,更新,删除)功能的简单应用程序而言,LINQ to SQL由于其简单性而非常理想。但是我个人喜欢使用NHibernate,因为它可以简化域。

编辑:@lomaxx-是的,我使用的示例过于简单,可以进行优化以与LINQ to SQL一起很好地工作。我想让它尽可能地基本,以使观点正确。关键在于,尽管在某些情况下,让数据库结构确定域结构是一个坏主意,或者至少会导致次优OO设计。


4
您可以使用Linq To SQL对存储库的实现进行编码,这非常方便。
Nicolas Dorier,2009年

1
我认为这不是ActiveRecord,甚至映射类也封装了一些基础结构逻辑。如果您可以拥有Customer.Save(),则为ActiveRecord模式。L2S使用DataContext类实现工作单元模式,就像nHibernate中的Session一样,但是NH具有真正的POCO方法。
Hrvoje Hudo 09年

1
@kevin“ LINQ to SQL使用活动记录模式”这是不正确的。这就像说ADO.NET使用活动记录,或者NHibernate使用活动记录。它们都是数据访问技术,并不强制执行任何特定的数据访问模式。我个人喜欢将linq-to-sql与存储库模式一起使用。您是正确的,linq-to-sql不像NHibernate那样支持复杂的映射。
liammclennan'5

1
相反,如何规范化数据库并让DAL由工具(如SQLMetal)生成?
亚历克斯(Alex)2010年

3
@CoffeeAddict当阻抗不匹配太大而无法承受时,那就是您的应用程序太复杂而无法在imo上使用LINQ to SQL。我的示例有臭味的原因是因为使用LINQ to SQL将导致8个属性,而不是2个,并限制了您执行诸如能够实现Address类的函数或在Address类上实现例程的操作的能力如果您使用过NHibernate,该怎么办。

26

迄今为止遗漏了两点:

而且,新的Nhibernate流畅接口似乎使配置Nhibernate的映射变得不那么麻烦。(消除了Nhibernate的痛苦之一)


更新资料

Linq to Nhiberate在现在处于Alpha的 Nhiberate v3中更好。看来Nhiberate v3可能会在今年年底推出。

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


2
Linq to NHibernate仍处于早期阶段。它不是一个完整的实现,并且可以说还没有准备好用于生产。
liammclennan

新的LinqConnect 2.0版本为方便起见引入了一些其他功能,例如“每种类型的表”继承支持,PLINQ支持和“批更新”功能。ORM设计器(Devart实体开发人员)现在具有“模型优先”支持和“映射同步”功能。更多详细信息:devart.com/news/2010/dotconnects600.html
Devart,

23

@Kevin:我认为您演示的示例的问题在于您使用的数据库设计不佳。我以为您会创建一个客户表和一个地址表并对其进行规范化。如果这样做,您可以针对您所建议的方案使用Linq To SQL。Scott Guthrie有大量有关使用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可以
自动为您执行此操作。


15
如果您针对无法支持的旧数据库结构编写代码,该怎么办,因为它支持其他应用程序。您是否要让域模型继承不良的数据库设计,还是要创建可以独立于数据库结构而变化的丰富域模型?
拉里·福克罗德

7

Fluent NHibernate可以基于简单约定生成映射文件。无需编写XML且具有强类型。

我最近参与了一个项目,出于性能原因,我们需要从Linq更改为SQL到NHibernate。特别是L2S实现对象的方法似乎比NHibernate的同上慢,并且变更管理也很慢。对于不需要的特定场景,可能很难关闭变更管理。

如果要使用与DataContext断开连接的实体-例如在WCF场景中-您可能会遇到很多麻烦,需要将它们再次连接到DataContext来更新更改。NHibernate对此没有任何问题。

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


2
以防万一其他人读了您的文章并且也考虑跳船- .ObjectTrackingEnabled = false这样您DataContext就可以解决变更跟踪问题。只要您采用工作单元模式并且不打算进行DDD,Linq-to-SQL确实可以提供。
mattmc3 2010年

出于性能原因,我们需要从Linq到SQL更改为NHibernate ” –我已经使用了[Fluent,不少于] NHibernate,这对您来说很有意义。我认为我们大部分时间都作弊,最终为真正的性能压力点编写了本机SQL。听到有关迁移方式的最新信息(六年后……),是否值得,将很有趣。
鲁芬2015年

5

您能否阐明“ LINQ”的含义?

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

许多人将LINQ To SQL称为LINQ,但这根本不正确。Microsoft刚刚发布了带有.NET 3.5 SP1的LINQ To Entities。另外,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的优点是可以在对象建模和数据库建模之间提供灵活性。可以对数据库进行建模,以在考虑性能的情况下最好地反映您的数据。虽然您的对象建模将使用诸如域驱动设计之类的方法来最好地反映业务规则的元素。(请参阅彭凯文的评论)

对于建模和/或命名约定不佳的旧数据库,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不支持

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.