所有已经讨论了的内容包括基本技巧,整合NHibernate和ASP.NET和单元测试。但是没有成功讨论的就是把这些技术包含在一个可升级的,可以再度使用体系结构。这个企业NHibernate样本定义了一个这样的例子,下面将讨论这个例子。当“企业”携带许多引申意义时,这篇文章使用这个单词来描述任何一个真实世界,ASP.NET应用程序支持的数据库。
为了建立企业样本,使其运转,除了前面在运转样本应用程序中描述的步骤以外,你需要执行下面的步骤。
1. 拉开企业样本到你选择的文件夹。
2. 在IIS里,创建新的虚拟的目录。别名必须是EnterpriseNHibernateSample,目录要指向EnterpriseSample.Web文件夹,当拉开应用程序后,就创建了EnterpriseSample.Web文件夹。
3. 打开EnterpriseSample.Web/Config/NorthwindNHibernate.config,修改数据库,此数据库连接符连接到微软SQL Server上的Northwind数据库。
4. 打开下面的文件,改变真个有资格的途径,这些途径指向EnterpriseSample.Web/Config/NorthwindNHibernate.config,(你的机器上的正确途径)。
o EnterpriseSample.Web/Web.config
o EnterpriseSample.Web/Config/CastleComponents.config
o EnterpriseSample.Tests/App.config
o EnterpriseSample.Tests/Globals.cs
我不喜欢在许多地址建立这个途径,我将把它仅仅集中在Web.config 和App.config.。看看现在该去哪里?想想怎样改进这些。
5. 打你的网络浏览器到http://localhost/EnterpriseNHibernateSample/Default.aspx,,你就完成了建立,可以运转了。
真实构架
尽管最好避免不成熟的一般化,但是用一个计划的很明智的结构体系开始项目发展很有好处。很容易扩展一个固定的结构体系根基,建立一个清晰的separation of concerns,为正在研究他们的开发者提供一个固定的指南。要在一般化和建立固定结构体系之间保持平衡。(在前面我进一步讨论了这个平衡)。尽管它不可能适合所有情况,企业样本应用程序显示了我所执著的,大尺寸ASP.NET项目中,又一个中等的固定结构体系结构。下面显示的是:一般的结构体系结构,包括具体的方向和接口依赖。

这里讨论了这个结构体系的高层结构,动机和假设。
Basics之上
企业示例通过以下方法扩展基本示例:
• AbstractNHibernateDao.cs, NHibernateSessionManager.cs, NHibernateSessionModule.cs, and IDao.cs已经被放到他们自己的可再度使用的/能扩展的项目中,此项目叫做ProjectBase.Data.
• DesignByContract.cs:已经被放到他们自己的克再度使用的/能扩展的项目中,此项目叫做ProjectBase.Utils。
• 已经增添了can't-debug-NHibernate-without-it log4net,并把它配置在web.config中。
• 磨损中有错误纪录IHttpModule。
• 已经更新了NHibernateSessionManager.cs,支持同时使用多个数据库。相应地文章Using NHibernate with Multiple Databases中描述的功能已经接到样本应用程序中去了。通过使用基本样本项目,你可能要把它转到单一数据库支持中。
• 设计模型Model-View-Presenter已经被ListCustomers.aspx and EditCustomer.aspx.应用到了分离的商业逻辑中。MVP版本与Supervising Controller的定义相符合。相应地,已经创建一个新项目(被命名为EnterpriseSample.Presenters)包括view interfaces and presenters。联合的单元测试已经补充到了EnterpriseSample.Tests.
• 已经补充了一个简单的网络服务GetCustomer.asmx,它与DTOs相反应,DTOs是从由被NHibernate恢复的数据组装的。请注意:不需要为这个例子考虑一个更好的方法例子。我是一个网络服务设计新手,我不确定与NHibernate整合有关的最优方法到底是什么。看看Where to go from here??因为在这个方面有一个额外的与进一步研究有关的注意事项。
GetCustomer.cs.中也包括了一些相关的评论。
• 已经整合了Castle Windsor,为网页、用户控制和网络服务,把DAO 工厂注入到控制器中。时刻记住,Castle Windso的综合利用远远不止这些。
仔细的看一下示例代码,但是第一眼的时候,可能让人畏缩(再多看几眼)。但是一旦所有的事情都准备好了,它就变得很强大,灵活,在最小程度上,不会攻击你正在开发的代码。
现在干什么?
如果你在读一篇关于正在兴起的技术的文章,这部分将被称作“进一步研究的方面”。因为那正是这里所描述的,我假设那个仅仅可以应用。这里有一些条目,它们将会被修改以获得更好的灵活性,或者被扩展以获得更大的可用性。这里有一些方法,能帮你补充你的空闲时间。
• 综合利用Guidance Automation Toolkit,捆扎方法到可装置的基本项目。
• NHibernate与网络服务整合中,最优方法不多。探索这个地方,至少定义“更好”方法将对NHibernate团体非常有趣。如果你有兴趣学习它,Thomas Erl's Service-Oriented Architecture是一个开始的好地方。
• 这个结构支持交易,这个交易以HTTP要求开始并结束。一个更理想的方案就是:当要开始交易时,使用属性来定义。在指定方法的结尾,就能开始交易。使用属性在NHibernateSessionManager类型上,能避免一个直接的dependency。一个例子属性就是[Transaction],被放在方法的顶端。而且,如果和不同的数据库工作,属性将包括某种ID指定,数据库通信要求一个交易,例如[Transaction("Primavera")].与Castle Project Automatic Transaction Management facility整合将是一个开始的好地方。
• 一些开发者抱怨:通过NHibernateSessionModule,使用Open-Session-in-View,为数字资产例如:图像和CSS文件,打开额外的,没有被使用的交易。在article's comments中,将找到一个讨论,后备解决方案。我很有兴趣能听到更进一步的与解决这个临时问题的建议(使用属性开始交易,正如在前面描述的,能解决这个问题) 。
• 多个数据库执行通过每一个数据库的config文件地址,正确地证明与那一个数据库相似,属于哪个ISession。在web.config和Castle Windsor配置文件中,这样导致了config文件的地址被复制。我喜欢去除这个复制,相反通过一个更简单的ID字符串,或者不需要将字符串传递到DAOs的构造者。
• 使用被提供的结构,不可能在两个数据库之间(这两个数据库位于不同的服务器上)操作一个单一的交易。可能要综合利用System.Transactions来解决这个问题。
• A 能为这个企业示例(包括CruiseControl.NET, NAnt (or MSBuild), NDepend, FxCop, SandCastle, NDbUnit, NStatic, 和 FIT/FitNesse.)创建一个模版Continuous Integration配置。
从NHibernate 1.0x到1.2
如果你正从NHibernate 1.0x更换到1.2,你肯定会发现一些改变。API改变的官方资料在NHibernate 1.2 Migration Guide中有介绍。下面列举了几条应该特别注意的:
• 1.2版本的所有类和集合都默认惰性载入。所以,如果你没有修改这个惰性属性而运行应用程序的话,你将会受到很多"method x should be virtual."可以通过为每一个你不想默认载入的类和集合设置lazy="false"来解决这个问题。
• 因为泛型的使用在这里被支持。所以你不再需要Ayende的NHibernate.Generics工具了。在我的devlicio.us的博客里有一个详细的例子refactoring away from Ayende's NHibernate.Generics。
在完成所有的转换到NHibernate 1.2的工作之后,最好为每一个父类别/子类别关系测试下面的事项:
• 通过父类别升级一个子类别,还工作吗?
• 创建一个新的子类别到父类别中去,数据库支持吗?
• 从父类别删除已存在的子类别,或者直接删除子类别,仍然正常工作吗?
• 其他的CRUD, cascade scenarios被测试了吗?
NHibernate/ASP.NET Best Practices总结
下面是在举例的应用程序里所体现出来的最优方法的快速总结:
• Business对象应该通过接口和数据存取对象通信。例如,总是依靠abstractions。
• 具体的数据存取对象应该使用"client",这个business逻辑层定义的接口。
• 通过一个abstract factory展示数据存取对象来帮助测试和降低耦合。
• 使NHibernate进程管理细节远离表示层和business逻辑层。
• 使用单元测试类来关闭依靠数据库连接的单元测试。
• 通过在web.config里设置hibernate.default_schema来给NHibernate一个好的性能。
我希望通过最优方法平衡ASP.NET, NHibernate和单元测试,这篇文章有帮助。现在通过这种方法我在自己的项目上已经获得了巨大的成功,同样我也希望能够听听你们的经验。如果你有任何问题和意见,请告诉我。如果你想知道任何时候我在忙什么,你可以在http://devlicio.us/blogs/billy_mccafferty上面找到我最新的留言。