2009-04-19 5 views
2

Я использую .net 2.0 с NHibernate/ActiveRecord и WCF.wcf serialization и nhibernate lazy loading

Я до сих пор не использовал нагрузку NH Lazy, но штрафы за производительность слишком велики, чтобы игнорировать, поэтому я начинаю использовать его.

Из того, что я прочитал до сих пор, это непростая тема, используя объекты NH с ленивой загрузкой и сериализации в WCF, но преимущества слишком велики, чтобы их игнорировать.

Использование кода Я нашел здесь: 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 на этих классах, сериализация работает просто отлично.

  1. Как DataContractSerializer решает, что сущность уже сериализована?
  2. Как я могу остановить это поведение?
  3. Возможно ли другой способ сериализации ленивых загрузочных объектов с WCF?

p.s. Я рассматриваю другое решение, создавая нечто похожее на NHibernate Proxy, но заменяю свойства, связанные с другими классами с необработанным ключом, поэтому вместо того, чтобы иметь свойство типа Branch, у меня было бы свойство типа int со значением 200. Таким образом, я мог бы избежать проблемы цикла, с которой столкнулся, но я бы попробовал это как последнее средство, так как было бы довольно сложно поддерживать.

Редактировать: У меня есть много сущностей, поэтому создание dto для каждого из них не может быть и речи, и создание его динамически было бы сложным, поэтому я бы предпочел избежать этого или использовать его в качестве последнего средства. Мне также нужно вести бизнес-логику на стороне сервера, поэтому мне понадобятся сущности, а не необработанные данные.

Редактировать: хорошо, не повезло, что прямой NH/AR/WCF. Я пойду с созданием DTO, который кажется более простым.

+1

Почему бы вам не создать DTO для использования в вашем веб-сервисе? – Paco

ответ

2

Я только что заметил, что я не закрыл свой вопрос, я пошел с решением DTO, и пока он работает нормально.

0

Слишком поздно отвечать ;-) Но так или иначе, это происходит из-за того, что ленивые объекты являются классами NH proxy; и кажется, что они различны, когда загружаются так. Одним из решений является переопределение .Equals() для сравнения свойства Id для постоянных объектов. Я предполагаю, что ваша сущность имеет что-то вроде первичного ключа. Это, вероятно, сделает WCF счастливым, только если он использует равенство, а не сравнение ссылок. Если WCF всегда использует ReferenceEquals - не повезло.

0

Мы использовали this решение и нашли, что это будет проще/лучше, чем решение DTO.