NHibernate 透明代理的副作用
一个bug调试了半天,才发现跟NHibernate透明代理有关。
用测试代码验证了一下:
ClassA有两个属性S1和S2,S1使用NHibernate持久化,S2不需要持久化。
测试代码:
输出结果:
CProxyTypeAA_CMSClassACMS_NHibernate_ProxyINHibernateProxy1
xxx ---
AA.CMS.ClassA
xxx --- yyy
session.Load()返回的实体对象都是一个透明代理,当访问这个透明代理的public方法(NHibernate要求这些方法都是virtual类型的,用于从它继承实现透明代理对象)时,构造出实际的实体对象。
问题表现在ClassB.Get()方法里面,它访问的是一个internal类型的属性S2,当传入的是一个透明代理时,internal的属性值S2无法获取到。可能是透明代理在internal类型的方法处理上有问题。
如果想基于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;
}
}
{
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>
<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;
}
}
{
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();
}
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使用充血模型,得好好注意透明代理的一些副作用了。