我将 .net 2.0 与 NHibernate/ActiveRecord 和 WCF 一起使用。
到目前为止我还没有使用过 NH Lazy load,但是性能损失太大而无法忽略,所以我开始使用它。
从我目前所读到的内容来看,这不是一个简单的主题,使用具有延迟加载和序列化到 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,则序列化工作得很好。
- DataContractSerializer 如何判断一个实体已经被序列化了?
- 我怎样才能阻止这种行为?
- 是否有其他方法可以使用 WCF 序列化延迟加载实体?
ps 我一直在考虑另一种解决方案,创建类似于 NHibernate Proxy 的东西,但是用原始键替换与其他类相关的属性,所以我没有一个 Branch 类型的属性,而是一个类型的属性int 的值为 200。这样我也许可以避免我遇到的循环问题,但我会尝试将此作为最后的手段,因为维护起来会非常复杂。
编辑:我有很多实体,所以为每个实体创建一个 dto 是不可能的,动态创建它会很复杂,所以我宁愿避免这种情况或将其用作最后的手段。我还需要在服务器端做业务逻辑,所以我需要实体而不是原始数据。
编辑:好吧,直接 NH/AR/WCF 的方式不走运。我将继续创建似乎更容易的 DTO。