NHibernate与LINQ to SQL
作为没有在现实世界项目中使用这两种技术的人,我想知道是否有人知道这两者是如何互补的以及它们的功能有多少重叠?
解决方案
回答
我们能否阐明" LINQ"的含义?
LINQ不是数据访问技术,它只是一种语言功能,支持将查询作为本机构造。它可以查询支持特定接口(例如IQueryable)的任何对象模型。
许多人将LINQ To SQL称为LINQ,但这根本不正确。 Microsoft刚刚发布了带有.NET 3.5 SP1的LINQ To Entities。另外,NHibernate具有LINQ接口,因此我们可以使用LINQ和NHibernate来获取数据。
回答
对于LINQ,我假设我们是指LINQ to SQL,因为LINQ本身没有与之关联的数据库。它只是一种查询语言,带有大量语法糖,使其看起来像SQL。
在最基本的基本示例中,NHibernate和LINQ to SQL似乎都在解决相同的问题。一旦获得通过,我们很快就会意识到NHibernate支持许多功能,这些功能使我们可以创建真正丰富的域模型。还有一个LINQ to NHibernate项目,该项目使我们可以使用LINQ来查询NHibernate,与使用LINQ to SQL的方式几乎相同。
回答
LINQ to SQL强制我们使用每类表模式。使用此模式的好处在于,它易于实现且易于操作,并且只需花费很少的精力即可使域基于现有的数据库结构运行。对于简单的应用程序,这是完全可以接受的(并且有时甚至更可取),但是对于更复杂的应用程序,开发人员通常会建议改用域驱动的设计模式(这是NHibernate所促进的)。
每类表模式的问题在于数据库结构对域设计有直接影响。例如,假设我们有一个"客户"表,其中包含以下列来保存客户的主要地址信息:
- 街道地址
- 城市
- 状态
- 压缩
现在,假设我们也要为客户的邮寄地址添加列,以便在"客户"表中添加以下列:
- MailingStreetAddress
- 邮寄城市
- 邮件状态
- 邮递区号
使用LINQ to SQL,我们域中的Customer对象现在将具有这八个列中每个列的属性。但是,如果我们遵循域驱动的设计模式,则可能已经创建了一个Address类,并且让Customer类拥有两个Address属性,一个属性用于邮件地址,另一个属性用于其当前地址。
这是一个简单的示例,但它演示了"按表创建表"模式如何导致有些臭味的域。最后,取决于我们。同样,对于只需要基本CRUD(创建,读取,更新,删除)功能的简单应用程序而言,LINQ to SQL由于其简单性而非常理想。但是我个人喜欢使用NHibernate,因为它可以简化域。
编辑:@lomaxx是的,我使用的示例过于简单,可以进行优化以与LINQ to SQL一起很好地工作。我想让它尽可能地基本,以便使观点正确。重点仍然是,尽管在某些情况下,让数据库结构确定域结构将是一个坏主意,或者至少会导致次优的OO设计。
回答
或者,我们可以使用Castle ActiveRecords项目。我已经使用了很短的时间来为遗留项目增加一些新代码。它使用NHibernate并在活动记录模式上工作(给定我所知道的名称,这令人惊讶)。我还没有尝试过,但是我假设一旦我们使用了它,如果我们感到需要直接获得NHibernate支持的话,那么对部分或者全部项目来说这样做就不是太多了。
回答
@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可以
为我们自动执行此操作。
回答
迄今为止遗漏了两点:
- LINQ to SQL不适用于Oracle或者SqlServer以外的任何数据库。但是,第三方确实为Oracle提供了更好的支持,例如devArt的dotConnect,DbLinq,Mindscape的LightSpeed和ALinq。 (我对此没有任何亲身经历)
- Linq to NHibernate使我们可以将Linq与Nhiberate一起使用,因此它可以消除不使用的原因。
而且,与Nhibernate的新的流畅接口似乎使配置Nhibernates映射的痛苦减轻了。 (消除了Nhibernate的痛苦之一)
更新
Linq to Nhiberate在现在处于Alpha版本的Nhiberate v3中更好。看来Nhiberate v3可能会在今年年底推出。
从.net 4开始的实体框架工作也开始看起来像是一个真正的选择。
回答
Fluent NHibernate可以基于简单约定生成映射文件。无需编写XML且具有强类型。
我最近参与了一个项目,出于性能原因,我们需要从Linq更改为SQL到NHibernate。特别是L2S实现对象的方式似乎比NHibernate的同上慢,而且变更管理也很慢。对于不需要的变更,可能很难关闭变更管理。
例如,如果要在WCF场景中使用与DataContext断开连接的实体,则可能会遇到很多麻烦,需要将它们再次连接到DataContext来更新更改。 NHibernate对此没有任何问题。
我会从L2S遗漏的东西主要是代码生成,该代码生成使实体两端的关系保持最新。但是我想NHibernate也有一些工具可以做到这一点...