将NHibernate应用程序重写为Linq to SQL

4

我有一个使用NHibernate编写的旧应用程序,现在我想重写它并包含新功能和模型中的大变化。

使用Linq to SQL而不是NHibernate的主要缺点是什么?

使用LINQ to SQL可能会出现哪些问题?将DataContext设置为类似单例的东西会导致性能差吗?


2
有没有特别需要使用LinqToSql重写它的原因?是否可以选择在NHibernate(最新版本)或Entity Framework中重写它? 所有这些不同的框架都提供不同的功能,所以一切取决于您的模型和关系是简单还是复杂... - RoelF
6个回答

8

来自"将数据访问封装在DAL中的错误神话":

"我想使用NHibernate设计一个系统/应用程序。但是,我也希望非常灵活,以便将来,如果我拔掉NHibernate并使用ADO.NET Entity Framework或其他框架,则我的应用程序不会崩溃。"

简而言之,我完全反对尝试做这样的事情。

它基于错误的假设

这背后的许多动力都是基于历史上建立的驱动程序,在那个时候,数据访问层直接使用其自己的方言访问数据库,导致需要创建这样的封装以支持多个数据库。

这个驱动的问题在于它已不再是一个因素,所有现代的ORM都可以有效地处理多个数据库。此外,现代的ORM不再只是执行一些SQL并获得结果的方式,这就是旧式DAL的编写方式。ORM承担了更多的责任,从变化跟踪到缓存管理,从确保乐观并发到管理与数据库的最佳通信等。
这些功能非常重要,而且它们在每个ORM之间也存在差异。
“它不起作用,你会发现太晚了”
主要问题在于无论你如何努力,不同的ORM之间都会有细微和不那么细微的差异,这些变化可能会极大地影响您构建应用程序的方式。
那么,如何在ORM之间移动呢?
有些人想从一种数据访问技术转移到另一种技术,这其中有很多原因。我参与了几个这样的努力,并且我们在每种情况下采用的方法是移植,而不是尝试放弃新的IDataAccess实现。

3

这是一个很大的问题,但在从L2S到NHibernate 2.x的大规模重构期间,我意识到NHibernate允许将基类表示为与派生类不同的物理表。但是,在L2S中,我被迫使用1个单一的表来表示基类和每个扩展它的类。

这使我能够创建较小的表,因为我有一个基类,由大约25个不同变体的子类继承。如果您希望以后使用此功能,它可以帮助简化架构。


一个基类被25个子类继承?听起来很糟糕(又复杂)。 - Rohith
哈哈,现在回头看,我很确定使用接口代替将所有人与基类耦合可能更好。然后通过组合,我可以重用相关的方法。 - Toran Billups

2
使用Linq to SQL而不是NHibernate的主要缺点是什么?
LINQ to SQL的优点
- 更高级和更易于使用(依我之见)的查询语法,具体而言它使用LINQ执行查询,这使得您获得强类型/编译时安全的查询。NHibernate提供了HQL,虽然相当强大,但全部基于字符串。NHibernate还有Criteria查询,它更强类型一些(仍然有一些字符串),但它的语法/API非常难以理解。 - NHibernate v2有一个你可以下载的LINQ提供程序,但它有点缺乏(实际上很缺乏),它不支持很多用例。NHibernate 3.0带有自己的内置LINQ提供程序,它更加强大,几乎与LINQ 2 SQL或EF齐平。
LINQ to SQL的缺点
- 几乎所有其他方面都有缺点!说真的,我从哪里开始: - 简单的表到实体映射,不像NHibernate具有更强大的映射功能,包括:单向关联、组件映射、您可以映射值类型的集合,例如public IList<string> Tags {get; set; },继承映射(非常强大),枚举映射,等等…… - 您的实体与LINQ to SQL紧密耦合,这可能会影响单元测试。NHibernate支持POCO映射,对于实现松散耦合、可维护、可单元测试的代码库非常重要。 - 支持更多数据库(SQL Server、MySql、PostgreSQL、Oracle、SQLite等)。LINQ 2 SQL仅支持MS SQL Server。 - 使用NHibernate可以在应用程序中实现DDD(领域驱动设计)原则。LINQ 2 SQL更多地是关注您的领域模型的数据库中心视图,而NHibernate则采用更具业务/行为中心的领域视图。
说真的,将NHibernate应用程序“降级”为LINQ 2 SQL似乎是一种倒退。如果您想使用更Microsofty的东西,请考虑使用Entity Framework 4.0。LINQ 2 SQL在只有几个表的简单应用程序中有其用武之地,但是任何更复杂的应用程序都需要更强大的ORM。

更高级的查询语法?为什么? - Diego Mijelshon
4
LINQ 2 SQL: 没有延迟加载。立即失败。 - rebelliard
别忘了在 NH 中使用 Linq 进行查询 :) - dbones
@Diego Mijelshon:也许“更高级”这个词用得不太恰当。或许更容易使用。我只是发现编写LINQ比编写HQL或ICriteria查询容易10倍,而且LINQ让我可以做任何事情(投影、分组、排序、连接、子查询等等)。难怪他们要在NHibernate 3.0中添加专门的LINQ实现。 - Sunday Ironfoot
这样说可能更准确,但我仍然不同意。LINQ到任何数据库技术都是高度泄漏的抽象,只有在您不知道(或不想学习)HQL时才更容易使用。 - Diego Mijelshon

1
也许你不需要进行完整的移植,只需要将NHibernate层转换为LINQ即可...

http://www.hookedonlinq.com/LINQToNHibernate.ashx

一些额外的阅读材料:

http://www.caffeinatedcoder.com/linq-to-nhibernate/

引用:

由于新的NHibernate LINQ提供程序,我现在可以以更安全的方式工作,而且代码也更易读。

看看这些查询之前和之后的变化,自己来评判:

之前(Criterion API)

   1: public IList<Call> GetCallsByDate(DateTime beginDate, int interpreterId)
   2: {
   3:     ICriteria criteria = Session.CreateCriteria(typeof(Call))
   4:         .CreateAlias("Customer", "Customer")
   5:         .Add(Restrictions.Gt("StartTime", beginDate))
   6:         .Add(
   7:            Restrictions.Or(
   8:                 Restrictions.Lt("EndTime", DateTime.Now), Restrictions.IsNull("EndTime")
   9:                 )
  10:             )
  11:         .Add(Restrictions.Eq("Interpreter.Id", interpreterId))
  12:         .AddOrder(Order.Desc("StartTime"))
  13:         .AddOrder(Order.Desc("Customer.Name"));
  14:
  15:     return criteria.List<Call>() as List<Call>;
  16: }

在(LINQ to NHibernate)之后
   1: public IList<Call> GetCallsByDateWithLinq(DateTime beginDate, int interpreterId)
   2: {
   3:     var query = from call in Session.Linq<Call>()
   4:                     where call.StartTime > beginDate
   5:                         && (call.EndTime == null || call.EndTime < DateTime.Now )
   6:                         && call.Interpreter.Id == interpreterId
   7:                     orderby call.StartTime descending, call.Customer.Name
   8:                     select call;
   9:
  10:     return query.ToList();
  11: }

1
当我构建一个应用程序时,如果它有一个简单的领域和基本的架构,我喜欢使用Linq2Sql。Linq编写起来很快,我可以快速完成任务。我知道有一个叫做Linq2NHibernate的东西,但我不确定它的成熟度如何。在我看来,Linq2Sql的一些缺点是必须在架构更改时重新生成类和DataContext,并且必须将Linq2Sql生成的类映射到我的领域对象中。对于小而简单的项目,我真的不介意这样做。虽然通过FluentNHibernate和Linq2NHibernate,我可能能够像使用Linq2Sql一样高效地使用NHibernate,但我还没有尝试过。
我曾经参与过一个项目,该项目在一个过度规范化的数据库上使用Linq2Sql,领域有些复杂,这是一场噩梦。它能够工作,我们能够从中获得良好的性能,但可维护性几乎不存在。但是由于架构的方式,我不确定NHibernate或纯SQL是否会改变这种情况。这是一个毫无疑问的案例,文档数据库无疑是最好的选择。
如果项目已经使用了NHibernate,并且你有相关经验,建议继续使用。直接将映射到你的领域对象的事实非常好。在开发早期架构发生变化时,Linq2Sql代码生成会很痛苦。除此之外,Linq2Sql基本上已经死亡。微软正在将其所有ORM资源投入到Entity Framework平台中。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接