NHibernate和多个数据库后端 - 架构

时间:2009-04-28 23:23:11

标签: .net asp.net nhibernate

我有一个项目应该在不同的(至少2个)数据库后端上运行,因此用户可以选择(目前在MSSQL和SQLite之间)。我刚刚开始学习NHibernate,遵循tutorial on nhibernate.info

现在,我目前的架构看起来像这样:

MyProject.DAL

包含 NewsItem INewsItemRepository 。 NewsItem是一个POCO,基本上只是一个int Id和字符串Title。

INewsItemRepository是包含CRUD功能的接口。

MyProject.Plugins.DAL.MSSQL

此类实现后端。它包括 hibernate.cfg.xml NewsItem.hbm.xml NewsItemRepository

cfg包含Driver和ConnectionString,hbm是特定于SQL Server的Mapping,而NewsItemRepository实现了INewsItemRepository。

如果我想添加MyProject.Plugins.DAL.SQLite,我将不得不复制所有这些,这是合乎逻辑的。但是,我想知道这是否是正确的方法?我觉得我不必要地重复一些事情。我的意思是:我需要确保映射是特定于数据库的,并且如果数据库发生更改,我会更新所有插件。但是这种架构似乎仍然不知所措......臃肿。

我在这里做对了吗?或者是否存在关于通用业务组合中的内容以及需要为每个数据库分开的内容的常见模式?

编辑:其中一个挑战是处理sql-types。例如,字符串默认情况下映射为nvarchar(255),如果我在MSSQL中需要ntext,我将不得不使用< column sql-type =“NTEXT”语法,是吗?我想指定sql-type是依赖于数据库的,所以我需要按照数据库分隔我的映射?或者是否有内置机制让映射相互“继承”? (即。在一般DAL项目中有一个.hbm.xml包含所有< property>标签,然后在包含列的每个后端程序集中都有.hbm?

3 个答案:

答案 0 :(得分:4)

好吧,我还没有看到您的项目或数据模型,所以您必须将其解释为最适合您的情况。但是,是的,我的反应是,这是更多的代码而不是必要的。

使用像NHibernate这样的ORM的一个主要好处是它们将您的代码与持久性架构分开。在我看来,多次映射NewsItem是不必要的。无论后端如何,数据模型都不一样吗?也许您可以举例说明它们可能存在差异。

其次,我可能不会重新实现NewsItemRepository。无论数据库后端如何,存储库都使用NHibernate,其主要目的是抽象数据库。存储库处理的所有CRUD功能在MSSQL上与SQLite相同(除非数据模型实际存在差异)。

如果两个后端的数据库模型相同,理论上您只需更改连接字符串即可更改正在使用的数据库。我之前实现DAL的方式是提供你已经完成的接口,然后为实现提供一个子命名空间,一个(好吧,目前唯一的一个;)是NHibernate。存储库等。通过依赖注入获得。 DI内核也处理会话工厂,因此很容易为不同的代码段定位不同的数据库。

当然,所有这些都假设您的数据模型在两个数据库引擎上都是相同的。如果不是,我的回答可能不是很有帮助。如果是这种情况,了解不同之处可能会让我或其他人得到更好的答案。

编辑:

我明白你对sql-type的意思了。但是,如果您从NHibernate生成数据库的架构,那么这只是一个问题。映射属性时, 不需要使用<column>,而<property>上指定的类型是NHibernate类型。 StringClob类型将正确处理NTEXT字段。

如果 从NHibernate映射生成模式 NHibernate不够智能去除SQLite的sql-type =“NTEXT”(我是希望它是,但我从未使用过模式生成工具),我想我会添加一个构建步骤来清理SQLite模式。当然,现在你正在为你的过程增加复杂性,所以这取决于你。但是,我宁愿保持我的代码和映射尽可能简单和干净,并且只在需要的地方保持复杂性(数据库引擎的挑剔细节)。在我看来,保留两个单独的映射文件是缺少属性映射的一个方法,用户在使用SQLite时为什么不能放入他们的DOB时感到头疼;)

EDIT2(与NH一起使用DI):

这有点主观,因为我确信有很多方法可以在NHibernate中使用DI。我使用DI Fluent NHibernateNinject取得了巨大的成功,这个DI框架也使用了“流畅的”DSL。 Fluent NHibernate(FNH)提供了一个接口IPersistenceConfigurer,用于创建数据库连接字符串(它还提供了许多方言可供选择)。因此,通过DI框架将IPersistenceConfigurer服务绑定到提供者很容易。您可以对ISessionFactory执行相同操作以完全注入D的工厂。由于Ninject处理属性,我的存储库构造函数可能如下所示:

[Inject, CRM]
public MyRepository(ISessionFactory sessionFactory)

哪个会为CRM数据库注入工厂。我喜欢。 :)

答案 1 :(得分:1)

NHibernate使用的数据类型取决于配置文件中使用的Dialect。当它处理xml时,它会为每个字段查找依赖于此方言的正确数据类型。您可以为每个数据库使用不同的方言,因此可以对整个项目使用相同的hbm.xml。

答案 2 :(得分:1)

我通过在配置文件中的连接字符串中配置代码中的会话工厂来处理动态切换数据库。我通过询问用户或阅读应用程序设置来决定使用哪个连接字符串。我使用依赖注入将ISessionFactory或ISession传递给您的存储库,通常将其传递给构造函数。

我没有任何针对多个数据库提供商的经验,所以我不知道你会遇到什么问题。