说说NHibernate any 标签的用法及查询

来自于一个我自己做着玩的项目 http://ornamentframework.googlecode.com/svn/trunk,里面有个关于用Any标签的例子。类关系如下:

 

Main

 

Info:信息对象

InfoReader:信息的读者

IPerformer: 用户标示Info能够被那些用户读取的。

Org、UserGroup、Role、User:组织单元。继承IPerformer,也就是Info.Readers的读者了之一。

 

    由于Org,UserGroup,Role,User之间也有复杂的关系,如果用3中继承方式,不但有速度的问题,而且在SaveOrUpdate中的Cascade也非常难处理,因此他们虽然都继承了IPerformer,但是在Mapping之中却是一点关系都没有。但是Info.Readers的Mapping应该怎样处理呢?首先看InfoReader的Reader,如下:

     
 
 /// <summary>
/// Gets or sets Reader
/// </summary>
public virtual IPerformer Reader { get; private set; }


然后重点是Mapping

 <any name="Reader" meta-type="String" id-type="Guid" >      
      <meta-value class="Ornament.MemberShip.User,Ornament.MemberShip.Core" value="Users" />
      <meta-value class="Ornament.MemberShip.UserGroup,Ornament.MemberShip.Core" value="UserGroups"/>
      <meta-value class="Ornament.MemberShip.Role,Ornament.MemberShip.Core" value="Roles"/>
      <meta-value class="Ornament.MemberShip.Org,Ornament.MemberShip.Core" value="Orgs" />
      <column name="ReaderType" length="20"/>
      <column name="ReaderId"/>
    </any>
 
    Any 属性中 Meta-type=”String” 对应是 <meta-value class="Ornament.MemberShip.User,Ornament.MemberShip.Core" value="Users" />  中的 Value, 即”Users”这个值,说明使用字符串。
id-type 就是下面所有对应的User/Ug/Role/Org的Id类型,他们都是Guid类型。然后下面就是个类型的meta-value标签,这个标签一定要出现在 Column标签之前,否则会报错,接下来,就是meta-type和id-Type
对应的Column名称,也是有顺序的,第一个对应是meta-type,第二个是id-type。
 
   使用SaveOrUpdate的结果如下:
   无标题 
 
插入,删除,更新都是小事,后来搞了老半天的查询才是关键.
原以为NH很智能,写了下面这个代码,我高估了NH,根本无法查到数据,永远返回0条数据。
DetachedCriteria cri = DetachedCriteria.For<Info>()
 .Add(Restrictions.In(“Reader”,User1,User2,Role1,Role2,ug1,ug2,org1,org2));

 

 

 

 

 

 

 

后来按照类型分开Restrictions.In就可以正确查询了。

 

   Any标记的好处非常明显,这个就不说了,但是他是有限制的,在新版本Nh2.02之后(1.2做过,是可以的),妄想把id-type=”String”,从而兼容所有Id类型的object,可以歇歇了。至少在SQLServer 2005中是不行了,不过SQLLite没有问题,其他的还没有测试。异常如下

[InvalidCastException: 对象必须实现 IConvertible。]
   System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) +7601433
   System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType) +4874600

[InvalidCastException: 将参数值从 Guid 转换到 String 失败。]
   System.Data.SqlClient.SqlParameter.CoerceValue(Object value, MetaType destinationType) +4874287
   System.Data.SqlClient.SqlParameter.GetCoercedValue() +32
   System.Data.SqlClient.SqlParameter.Validate(Int32 index, Boolean isCommandProc) +100
   System.Data.SqlClient.SqlCommand.BuildParamList(TdsParser parser, SqlParameterCollection parameters) +203
   System.Data.SqlClient.SqlCommand.BuildExecuteSql(CommandBehavior behavior, String commandText, SqlParameterCollection parameters, _SqlRPC& rpc) +237
   System.Data.SqlClient.SqlCommand.AddBatchCommand(String commandText, SqlParameterCollection parameters, CommandType cmdType) +94
   System.Data.SqlClient.SqlCommandSet.ExecuteNonQuery() +255
   NHibernate.AdoNet.SqlClientSqlCommandSet.ExecuteNonQuery() +62
posted @ 2010-06-10 23:14  沉默的糕点  阅读(1020)  评论(5编辑  收藏  举报