Posted on 2007-09-04 17:29
Glen 阅读(3281)
评论(0) 编辑 收藏 所属分类:
ORMapping
项目的框架已经完成,今天把两个不是很确定的知识点进行学习,并实现例程。但是其中还有一些知识点也只是在项目中实现了,并还没有去深入的学习。只是把项目中应用的一些经验总结,以便在我们以后的项目中更好的应用NHibernate。
1.数据类型对应
数据库中以二进制形式存储的类型,如binary,varbinanry,image等都可以映射成NHibernate中Byte数组,c#中也为byte数组,但是要注意大小写。
数据库中以字符串形式存储的类型,如varchar,nvarchar,char,ntext等可以映射成NHibernate中的String类型,c#中的string类型
数据库中的以数字形式存储的类型,如int,float,decimal等,对应到相应的数据类型即可。
数据库中系统表中的sysname类型对应到string
Nhibernate中还有BinaryBlob和StringClob两个类型,前者对应到数据库中的二进制,对应到c#中byte数组。后者对应到数据库中字符串类型,对应到c#中的string。两者都是用来处理数据长度较大的情况,使用并无特别之处。
在使用时发现部分数据类型之间的对应关系并不是严格限定的,如数据库中tinyint既可以映射成int类型,也可以映射成Byte,还有ntext可以对应到String和StringClob,灵活性比较大。详细的对应关系可以参考NHibernate文档中第四章O/R Mapping基础中的NHibernate 的类型一节。例子可以参考NHibernate\src\src\NHibernate.Test\TypesTest。注意点Nhibernate是区分大小的,如果有误是会报错的。
2.使用联合主键进行表间映射
这个知识点好像很难用文字描述清楚,附代码讲解会比较容易理解。
映射中用到的表:
table
|
person
|
Key
|
Column
|
★
|
id
|
★
|
name
|
table
|
account
|
Key
|
Column
|
★
|
account_no
|
★
|
person_name
|
★
|
Person_id
|
person与account的关系是一对多,通过person表中id,name和account中Person_id ,person_name进行关联。
person的映射配置文件为:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="NHibernateTest.Entity.Person,NHibernateTest.Entity" table="person">
<composite-id>
<key-property name="Id" column="id" type="String"/>
<key-property column="name" type="String" name="Name" />
</composite-id>//声明联合主键
<bag name="Accounts" inverse="true" lazy="true">
<key>
<column
name="person_id" />
<column
name="person_name"/>//声明关联的栏位
</key >
<one-to-many class="NHibernateTest.Entity.Account,NHibernateTest.Entity"/>//声明一对多关系
</bag>
</class>
</hibernate-mapping>
|
Account表映射配置文件:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="NHibernateTest.Entity.Account,NHibernateTest.Entity" table="account">
<composite-id>
<key-property column="account_no" type="String" name="AccountNo"/>
<key-many-to-one name="OnePerson" class="NHibernateTest.Entity.Person,NHibernateTest.Entity">
<column
name="person_id"/>
<column
name="person_name"/>//声明关联的栏位
</key-many-to-one>//声明多对一关系
</composite-id>
<property column="person_id"
type="String" name="PersonId" update="false"
insert="false"/>
<property
column="person_name" type="String"
name="PersonName" update="false"
insert="false"/> //通过设置update与insert为false,声明属性为只读
<property column="balance" type="Decimal" name="Balance" />
</class>
</hibernate-mapping>
|
注意点:在用到联合主键的实体类中,重写的Equals方法很重要,在Nhibernate在做数据筛选的时候,会用到Equals方法,如果Equals方法不准确的话,查询出来的数据是会有问题的。Equals方法设计原则是一定要保证数据的唯一性。Account类中的Equals方法
public override bool Equals( object
obj )
{
if( this == obj ) return
true;
if( (
obj == null ) || ( obj.GetType() != this.GetType() ) ) return
false;
Account
castObj = (Account)obj;
return
(castObj!=null)&&(this.AccountNo.Equals(castObj.AccountNo)
&&(this.OnePerson.Id.Equals(castObj.OnePerson.Id)
&&this.OnePerson.Name.Equals(castObj.OnePerson.Name)));//请注意红色字体部分
}
|
关于集合之间的对应问题,NHibernate中的bag和list可以对应到C#中的List,而因为C#中没有set这个集合,NHibernate用到第三方的set实现方法,如果需要要set对应必须引用Iesi.Collections.dll
相关知识点还可以参考nhibernet\src\src\NHibernate.DomainModel下的Inner,Middle和Outer,但是这些例子因为没有数据表对应,所以看起来会比较困难点。
3.使用同一个连接访问不同的数据库(针对sql server)
这个应该算是一个应用的小技巧了,只需要在映射文件的表名前加上库名就ok了,注意下面的代码的斜体部分。
<class name="NHibernateTest.Entity.Class,NHibernateTest.Entity" table="DatabaseName.dbo.tablename">
|
NHibernate在用到这个映射时会自动访问相应的database,同时再次访问项目中配置好的database也不会有问题。同一个连接可以在不同database之间切换。
做人简单一点好