NHibernate 透明代理的副作用

一个bug调试了半天,才发现跟NHibernate透明代理有关。
用测试代码验证了一下:
ClassA有两个属性S1和S2,S1使用NHibernate持久化,S2不需要持久化。

public   class  ClassA
{
    
private   int  _id;
    
private   string  _s1;
    
private   string  _s2;

    
public   virtual   int  ID
    {
        
get  {  return   this ._id; }
        
set  {  this ._id  =  value; }
    }

    
public   virtual   string  S1
    {
        
get  {  return   this ._s1; }
        
set  {  this ._s1  =  value; }
    }

    
internal   virtual   string  S2
    {
        
get  {  return   this ._s2; }
    }

    
public   virtual  ClassA DoSomething( string  s1,  string  s2)
    {
        
this ._s1  =  s1;
        
this ._s2  =  s2;
        
return   this ;
    }
}

<? xml version="1.0" encoding="utf-8"  ?>
< hibernate-mapping  xmlns ="urn:nhibernate-mapping-2.2"  namespace ="AA.CMS"  assembly ="aa.cms" >
    
< class  name ="ClassA"  table ="TableA" >
        
< id  name ="ID"   >
            
< column  name ="ID"  sql-type ="NUMBER(8,0)"  not-null ="true" />
            
< generator  class ="assigned"   />
        
</ id >
        
< property  name ="S1"   >
            
< column  name ="S1"  sql-type ="NVARCHAR2"  length ="25"  not-null ="false" />
        
</ property >
    
</ class >
</ hibernate-mapping >

public   class  ClassB
{
    
public   string  Get(ClassA a)
    {
        
return  a.S2;
    }
}

测试代码:
[Test]
public   void  Test()
{
    ISession session 
=  TestSetup.GetSession();
    ClassA a1 
=  session.Load < ClassA > ( 1 );
    ClassA a2 
=  a1.DoSomething( " xxx " " yyy " );
    ClassB b 
=   new  ClassB();

    DebugUtil.Output(a1.GetType().FullName);
    DebugUtil.Output(a1.S1 
+   "  ---  "   +  b.Get(a1));
    DebugUtil.Output(a2.GetType().FullName);
    DebugUtil.Output(a2.S1 
+   "  ---  "   +  b.Get(a2));
    session.Close();
}

输出结果:
CProxyTypeAA_CMSClassACMS_NHibernate_ProxyINHibernateProxy1
xxx ---
AA.CMS.ClassA
xxx --- yyy

session.Load()返回的实体对象都是一个透明代理,当访问这个透明代理的public方法 (NHibernate要求这些方法都是virtual类型的,用于从它继承实现透明代理对象)时,构造出实际的实体对象。
问题表现在ClassB.Get()方法里面,它访问的是一个internal类型的属性S2,当传入的是一个透明代理时,internal的属性值S2无法获取到。可能是透明代理在internal类型的方法处理上有问题。

如果想基于NHibernate使用充血模型,得好好注意透明代理的一些副作用了。

你可能感兴趣的:(Hibernate)