Я использую .net 2.0 с NHibernate / ActiveRecord и WCF.
До сих пор я не использовал загрузку NH Lazy, но потери производительности слишком велики, чтобы их игнорировать, поэтому я начинаю использовать ее.
Из того, что я читал до сих пор, это непростая тема, использующая сущности NH с отложенной загрузкой и сериализацией в WCF, но преимущества слишком велики, чтобы их игнорировать.
Используя код, который я нашел здесь: Сериализация WCF С 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?
p.s. Я рассматривал другое решение - создать нечто похожее на NHibernate Proxy, но заменить свойства, относящиеся к другим классам, на необработанный ключ, поэтому вместо свойства типа Branch у меня будет свойство типа int. со значением 200. Таким образом, я мог бы избежать проблемы с циклом, с которой столкнулся, но я бы попробовал это как последнее средство, так как его было бы довольно сложно поддерживать.
edit: у меня много сущностей, поэтому о создании dto для каждой из них не может быть и речи, и создать его динамически было бы сложно, поэтому я бы предпочел этого избегать или использовать в качестве крайней меры. Мне также нужно заниматься бизнес-логикой на стороне сервера, поэтому мне понадобятся не сущности, а сущности.
редактировать: ну, не повезло, если вы идете прямым путем NH / AR / WCF. Я пойду с созданием DTO, который кажется более простым.