2009-10-29 9 views
9

Mam dziwny problem w moim bieżącym projekcie. Leniwe ładowanie zapytań nie działa. Kiedy wysyłam zapytanie do listy, nhibernate pobiera wszystkie powiązania osobno.NHibernate tworzy proxy za pomocą session.Load(), ale nie poprzez Linq lub API Criteria

Wyciągnąłem małe jego części i ułożyłem w osobne rozwiązanie. Zasadniczo mam teraz tabelę kont i tabelę AccountSync. Oba mają identyfikator i adres URL, a identyfikator to tylko db-guid.

Moje zajęcia są:

public class HippoAccount 
{ 
    public virtual Guid Id { get; set; } 
    public virtual string Url { get; set; } 
    public virtual HippoAccountSync Sync { get; set; } 
} 

public class HippoAccountSync 
{ 
    public virtual Guid Id { get; set; } 

    public virtual string Url { get; set; } 
    public virtual HippoAccount Account { get; set; } 
} 

Kiedy teraz załadować obiektu poprzez jego GUID:

var account = session.Load<HippoAccount>(accountId); 
Console.WriteLine(NHibernateUtil.IsPropertyInitialized(account, "Sync")) 

... zwraca false i sam rachunek jest proxy.

Ale kiedy ładuje listę poprzez kryteria API:

var account = (HippoAccount)session 
    .CreateCriteria(typeof (HippoAccount)) 
    .Add(Restrictions.Eq("Id", accountId)) 
    .List()[0]; 

... własność Sync zostanie zainicjowana (wypalanie drugą kwerendę wybierającą) i zwrócony obiekt nie jest proxy.

Czy to domyślne zachowanie? Co robię źle?

Odwzorowanie jest:

<class name="HippoAccount" table="AllAccounts"> 
    <id name="Id" type="guid"> 
    <generator class="guid"/> 
    </id> 
    <property name="Url" /> 

    <many-to-one 
      class="HippoAccountSync" 
      name="Sync" 
      not-found="ignore" 
      property-ref="Url"> 
    <column name="url" /> 
    </many-to-one> 
</class> 

<class name="HippoAccountSync" 
     mutable="false" 
     table="Accounts"> 

    <id name="Id" type="guid"> 
    <generator class="guid"/> 
    </id> 

    <property name="Url"> 
    <column name="serviceUri" /> 
    </property> 

    <many-to-one class="HippoAccount" 
       name="Account" 
       property-ref="Url" 
       not-found="ignore"> 

    <column name="serviceUri" /> 
    </many-to-one> 

</class> 
+0

nie wiem, czy to całkowicie związane, ale są problemy z nie-found = "ignoruj": http://nhjira.koah.net/browse/NH-1001 http: //guildsocial.web703 .discountasp.net/dasblogce/CommentView, guid, ba00b19d-bd60-442b-b2e7-935277a9f1eb.aspx –

+0

Masz rację. Kolejną kwestią jest właściwość-ref - wyłącza również leniwy ładowanie. http://maonet.wordpress.com/2007/12/05/lazy-load-conflicts-with-property-ref-in-mem-to-one-mapping/ –

Odpowiedz

10

Po jakiś dalszych badań, znalazłem odpowiedź. Odpowiedzi, ponieważ istnieje wiele rzeczy, które mogą zapobiec leniwemu ładowaniu w NHibernate.

  1. Zapytanie vs. session.Load: Podczas pobierania elementu poprzez session.Load() masz proxy. Ale jak tylko uzyskasz dostęp do dowolnej właściwości, powiedzmy, że Url, obiekt jest pobierany, włączając wszystkie jego powiązania, które nie obsługują leniwego ładowania.

  2. property-ref: Leniwe ładowanie działa tylko nad identyfikatorem obiektu. Kiedy powiązanie własności zostanie rozwiązane przez inną kolumnę w jednostce docelowej, NH pobiera ją z zapałem. Nie dlatego, że nie byłoby to możliwe, to po prostu nie wdrożone: not-found Bug

  3. = "ignoruj" pozwala nieprawidłowe klucze obce, to znaczy, jeżeli powołany podmiot nie znajduje NH uruchomi właściwość z wartością null. NH nie przechwytuje dostępu do właściwości dla leniwego ładowania, ale zamiast tego przydziela proxy obiektu. Z not-found="ignore" nie może zdecydować, czy właściwość ma być ustawiona na wartość null, czy też proxy dla danego, potencjalnie nieważnego, klucza obcego. Można to rozwiązać, przechwytując dostęp do właściwości.

  4. Po wyłączeniu not-found="ignore" i property-ref eksport schematu wygeneruje ograniczenia wymuszające odwołanie cykliczne. Niedobrze! Prawidłowe odwzorowanie byłoby wówczas ograniczoną relacją jeden-do-jednego, gdzie klucz dla HippoAccountSync musi mieć generator foreign.

Resources

+0

Z session.Load(), możesz, oczywiście, bezpiecznie uzyskaj dostęp do właściwości Id serwera proxy bez trafiania do bazy danych, ponieważ dałeś serwerowi identyfikator od samego początku. – Jay

+0

link do błędu w obiekcie-ref już nie istnieje, błąd 404. Masz pomysł na ten postęp? – shanabus

Powiązane problemy