ERP/MIS开发 Mindscape NHibernate + MySQL 快速开发入门
ORM设计工具:Mindscape NHibernate Designer,请安装Mindscape.NHibernateModelDesigner.vsix文件。
它是一个Visual Studio 2010的插件,运行时效果所示
支持Model frist和Database first两种开发模式,如下图所示
Update Model from Database,从数据库schema更新模型定义
Update Database from Model 则是以实体定义更新数据库。
设计器会生成一个组件layout文件,用于设计器工作,一个cs文件,对应于实体属性与数据库字段映射,Agent内容如下
public partial class Agent
{
public virtual string Name { get; set; }
public virtual string Position { get; set; }
public virtual string Description { get; set; }
static partial void CustomizeMappingDocument(System.Xml.Linq.XDocument mappingDocument);
internal static System.Xml.Linq.XDocument MappingXml
{
get
{
var mappingDocument = System.Xml.Linq.XDocument.Parse(@"<?xml version='1.0' encoding='utf-8' ?>
<hibernate-mapping xmlns='urn:nhibernate-mapping-2.2'
assembly='" + typeof(Agent).Assembly.GetName().Name + @"'
namespace='BusinessLogic'
>
<class name='Agent'
table='`Agent`'
>
<id name='Name'
column='`Name`'
>
<generator class='identity'>
</generator>
</id>
<property name='Position'
column='`Position`'
/>
<property name='Description'
column='`Description`'
/>
</class>
</hibernate-mapping>");
CustomizeMappingDocument(mappingDocument);
return mappingDocument;
}
}
}
MappingXml的值,就是我们开发NHibernate时需要配置的映射文件,由设计器维护。
数据库选用MySQL 5.1。
MySQL 数据表的创建
SQL脚本如下
DROP TABLE IF EXISTS `ctu`.`agent`;
CREATE TABLE `ctu`.`agent` (
`Name` varchar(40) NOT NULL,
`Position` varchar(45) NOT NULL,
`Description` varchar(45) NOT NULL,
PRIMARY KEY (`Name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
先查看一下这个表的数据项,有三笔数据,分别以Jack,Tony,Charles为主键
启动Visual Studio 2010,打开Server Explorer,创建一个新的MySQL连接
记住这里要勾选Allow saving password,否则当把表拖动到设计器中时,会出现无法连接的异常
把表CTU拖动到NHibernate设计器中,以完成模型的创建
在设计器中右键,调出Get Started菜单项
如图所示,已经写好了配置文件的主要内容,添加App.config或Web.config文件,把配置内容拷贝到文件中
<configSections>
<section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
</configSections>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">NHibernate.Dialect.MySQL5Dialect</property>
<property name="connection.connection_string">User Id=root;Password=123;Host=JAMESLI;Database=ctu;Persist Security Info=True;</property>
<property name='proxyfactory.factory_class'>NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
</session-factory>
</hibernate-configuration>
在项目的启动目录中,添加这2个程序集:NHibernate.ByteCode.Castle.dll和Castle.Core.dll
把Get Started中的NHibernateHelper文件拷贝到项目中
public static class NHibernateHelper
{
private static ISessionFactory _sessionFactory;
internal static ISessionFactory SessionFactory
{
get
{
if (_sessionFactory == null)
{
var configuration = ConfigurationHelper.CreateConfiguration();
_sessionFactory = configuration.BuildSessionFactory();
}
return _sessionFactory;
}
}
internal static ISession OpenSession()
{
return SessionFactory.OpenSession();
}
}
设计如下的测试代码
[TestMethod]
public void TestFetch()
{
using (ISession session = NHibernateHelper.OpenSession())
using (ITransaction tx = session.BeginTransaction())
{
string name = "Tony";
Agent tony = session.Get<Agent>(name);
string fullName = tony.Description;
}
}
启动调试器,进入方法中,效果如下图所示
这表明,NHibernate已经成功的从MySQL数据库中取得了数据记录。
从.NET 1.1起,NHibernate就是极力推荐的ORM开发工具。因为没有称心的ORM设计工具,维护数据库字段与实体属性之间的映射关系非常麻烦,而且容易出错。商业的ORM工具,卖点之一就是简化映射文件的设计。不管是用xml文件或是cs文件来维护映射,只要维护关系映射简单,就是很大的进步,如果能熟练操作文章中提到的数据库与实体映射的内容,用NHibernate来开发ERP/MIS应该是很简单轻巧的事情。
写完了这篇文档,检查NHibernate文档,发生有个NHibernate.Tool.hbm2net的软件,解释如下
NHibernate.Tool.hbm2net 是 NHibernate 的附加软件.它使得从hbm.xml映射文件产生源代码成为可能。
在 NHibernate.Tasks目录,有一个叫做Hbm2NetTask的工具,你可以用它自动编译程序(使用NAnt)。
温故而知新,NHibernate拥有很多实用工具,再推荐一个工具NHibernate Profiler工具
在应用程序中添加对HibernatingRhinos.NHibernate.Profiler.Appender.dll程序集的引用,并在启动时添加代码
[TestInitialize]
public void InitializeProfiler()
{
HibernatingRhinos.NHibernate.Profiler.Appender.NHibernateProfiler.Initialize();
}
HibernatingRhinos.NHibernate.Profiler.Appender.NHibernateProfiler.Initialize();
以插入跟踪程序,再启动之前的测试方法,切换到NHibernate Profiler的界面中即可看到被发送到服务器的SQL语句。
当然,也可以用SQL Server Profiler来追踪出问题的SQL语句,举例说明
SalesOrderEntity salesOrder=session.Get<SalesOrderEntity>(5023);
这是用主键来查找数据记录,通常不会有问题。反过来,写两个SQL来对比一下,请看以下两条SQL
SELECT * FROM SalesOrder WHERE CustomerId is NULL
SELECT * FROM SalesOrder WHERE CustomerId =’’
这两句,从SQL的层面来理解,前一句是找出客户编号为空的采购单,后一句是找出客户编号为空白的采购单
对应于CustomerId,一般会用string类型来映射。如果有语句将CustomerId 初试化为string.Empty,而另一段代码
却没有初试化CustomerId,意味着CustomerId为null,这两个ORM语句发送到服务器中去,就会是两种不同的WHERE条件,即CustomerId =’’和CustomerId is NULL,也就是发送的ORM语句与实际SQL查询的结果不一致。
ORM开发中,出现ORM语句的语意与我们设想的SQL不同时,可使用NHibernate Profiler或SQL Server Profiler来追踪有问题的SQL语句,从而修改ORM的写法来排除错误。