我正在使用带有NHibernate / ActiveRecord和WCF的.net 2.0。
到目前为止,我还没有使用NH Lazy加载,但性能损失太大而不能忽略,所以我开始使用它。
从我到目前为止所读到的内容来看,使用延迟加载和序列化到WCF的NH实体并不是一个简单的主题,但是它的好处太大了,不容忽视。
使用我在此处找到的代码:WCF Serialization With NHibernate,我已经能够让WCF识别基本类型。
我也是这样创建DataContractSerializer:
public override XmlObjectSerializer CreateSerializer(Type standard, XmlDictionaryString name, XmlDictionaryString NS, IList<Type> knownTypes)
{
return new DataContractSerializer(standard, name, NS, knownTypes, 0x989680, false, true /* Preserve References*/, new HibernateDataContractSurrogate());
}
我的问题是当我有这样的事情时:
[DataContract, ActiveRecord("POS_POSCUSTOMERS",Lazy = true)]
public class POSCustomer : ActiveRecordForPOS<POSCustomer>
{
private Branch belongsToBranch;
[DataMember,BelongsTo("BRANCH")]
public virtual Branch BelongsToBranch
{
get { return belongsToBranch; }
set { belongsToBranch = value; }
}
}
和
[DataContract, ActiveRecord("BRANCHES",Lazy = true)]
public class Branch : ActiveRecordForPOS<Branch>
{
private POSCustomer defaultPOSCustomer;
[DataMember, BelongsTo("POS_POSCUSTNUM", Cascade= CascadeEnum.None)]
public virtual POSCustomer DefaultPOSCustomer
{
get { return defaultPOSCustomer; }
set { defaultPOSCustomer = value; }
}
}
Branch.DefaultPOSCustomer和POSCustomer.BelongsToBranch是两个不相关的实体,但它们是相同的实体,例如Branch 200具有DefaultPOSCustomer 100,而POSCustomer具有BelongsToBranch 200。
问题在于,当WCF尝试序列化对象图时,它会在DefaultPOSCustomer和BelongsToBranch之间反弹,好像不会识别出它们是相同的实体并且已经将它们序列化,直到它遇到堆栈溢出
如果我在这些类上关闭Lazy = true,序列化就可以了。
P.S。我一直在考虑另一个解决方案,创建类似于NHibernate Proxy的东西,但用原始键替换与其他类相关的属性,所以我没有类型为Branch的属性,而是有一个int类型的属性这样我可以避免我遇到的循环问题,但我会尝试将其作为最后的手段,因为维护它会非常复杂。
编辑:我有很多实体,所以为每个实体创建一个dto是不可能的,动态创建它会很复杂,所以我宁愿避免使用它,也不要将它作为最后的手段使用。我还需要在服务器端执行业务逻辑,因此我需要实体而不是原始数据。
编辑:好吧,没有运气直接的NH / AR / WCF方式。我会选择创建看似简单的DTO。
答案 0 :(得分:2)
我刚注意到我没有关闭我的问题,我选择了DTO解决方案,到目前为止工作正常。
答案 1 :(得分:0)
回答为时已晚;-)但无论如何,这是因为延迟加载的对象是NH代理类;并且看起来像这样加载时它们是不同的。 一种解决方案是覆盖.Equals()以比较持久实体的Id属性。我想你的实体有类似主键的东西。这可能会使WCF满意,只有它使用相等而不是引用比较。如果WCF总是使用ReferenceEquals - 没有运气。
答案 2 :(得分:0)
我们一直在使用this解决方案,并且发现它比DTO解决方案更容易/更好。