Richie

Sometimes at night when I look up at the stars, and see the whole sky just laid out there, don't you think I ain't remembering it all. I still got dreams like anybody else, and ever so often, I am thinking about how things might of been. And then, all of a sudden, I'm forty, fifty, sixty years old, you know?

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使用充血模型,得好好注意透明代理的一些副作用了。

posted on 2007-08-27 00:35  riccc  阅读(884)  评论(0编辑  收藏  举报

导航