前言
通过使用NHibernate.Mapping.Attributes命名空间中的方法,可以不用写实体类的配置hbm.xml文件,只需要在相应实体类上加上适当标签,可以较大程度的提高开发效率,减少开发时间,并且不用再为那扰人的xml而烦扰。
1.原理
就是通过反射查找相应对象上的标签,然后动态生成与之前对应的hbm.xml流,然后加载至Configuration中。可见通过该种方式最重要的是相应的对象上加上正确并且需要的标签。这样就可以不再写或修改那烦人的xml文件。
2.准备工作
必须导入NHibernate.Mapping.Attributes命名空间,该命名空间属于NHibernate.Mapping.Attributes.dll文件中,该文件在NHibernateContrib-0.9.0.0中,可以到NHibernate网站下载。本文测试所采用的NHibernate和NHibernateContrib均是在0.9.0.0上测试通过。
3.如何加入标签
a.class上至少需加上[ClassAttribute(Table=Children)]
对应生成的xml片断如下
<class name='Models.Children, Models' table='Children'>
b.Id上加上如下所示标签
[Id(0, Name='Id',TypeType=typeof (int),Column='Id',UnsavedValue='0')]
[Key(1)]
[Generator(2, int Id
{
get { return _id; }
set { _id = value; }
}
其中0,1,2表示生成xml文件时属性的顺序,以上的标签最后生成可能是以下xml片断
<id name='Id' column='Id' type='Int32' unsaved-value='0'>
<generator />
</id>
c.其他一般属性需加上如下标签
[PropertyAttribute(Column='PName',Length=50,TypeType=typeof(String))]
public string PName
{
get { return _pName; }
set { _pName = value; }
}
对应xml片断
<property name='PName' type='String' column='PName' length='50' />
d.对于一对多情况加上如下标签
[Bag(0,Table='Children', Lazy=true, Cascade=CascadeStyle.All)]
[Key(1, Column='ParentId')]
[OneToManyAttribute(2, ClassType=typeof(Children))]
public IList Children
{
get { return _children; }
set { _children = value; }
}
对应xml片断如下
<bag name='Children' table='Children' lazy='true' cascade='all'>
<key column='ParentId' />
<one-to-many Models' />
</bag>
e.对于多对一的情况加上如下标签
[ManyToOne(0, ClassType=typeof (Parent),Column='ParentId',OuterJoin = OuterJoinStrategy.True)]
public Parent Parent
{
get { return _parent; }
set { _parent = value; }
}
对应的xml片断
<many-to-one name='Parent' Models' column='ParentId' outer-join='true' />
4.类写好了,标签也加上了,可以采用如下方式加入到Configuration
Configuration cfg = new Configuration();
using(MemoryStream stream = new MemoryStream())
{
for(int i=0;i<config.Count;i++)
{
HbmSerializer.Serialize(stream, System.Reflection.Assembly.Load('models'));
stream.Position = 0;
cfg.AddInputStream(stream);
}
}
4.容易出现的问题
漏掉标签,如:在Id上漏掉Name导致Search出来的对象Id都是0,漏掉级联或是其他
5.解决方法
a.可以将其动态产生的xml文件流输出到一个xml文件中,然后将输出的xml文件和之前的xml文件比对容易发现问题
输出到xml文件的代码如下:
FileStream fs = new FileStream(@'d:\DynamicHibernateMapping.xml',FileMode.Create);
fs.Write(stream.ToArray(),0,(Int32)stream.Length);
fs.Close();
b.列出一个属性标签清单,进行对比也可以
6.其他问题
欢迎私下交流,msn:eJimGao@msn.com
7.Table DDL
CREATE TABLE [dbo].[Children] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[CName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[ParentId] [int] NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Parent] (
[Id] [int] IDENTITY (1, 1) NOT NULL ,
[PName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]