Domanda

Ho un problema strano nel mio attuale progetto. Il caricamento lento per le query non funziona. Quando eseguo una query su un elenco, nhibernate recupera tutte le associazioni separatamente.

Ne ho estratto piccole parti e l'ho messo in una soluzione separata. Fondamentalmente quello che ho ora è una tabella dei conti e una tabella dei conti. Entrambi hanno un ID e un URL, mentre l'ID è solo un db-guid.

Le mie lezioni sono:

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; }
}

Quando ora carico un oggetto tramite il suo guid:

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

... restituisce false e l'account stesso è un proxy.

Ma quando si carica un elenco tramite l'API dei criteri:

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

... la proprietà Sync viene inizializzata (attivando una seconda query di selezione) e l'oggetto restituito non è un proxy.

È un comportamento predefinito? Cosa mi sbaglio?

La mappatura è:

<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>
È stato utile?

Soluzione

Dopo alcune altre ricerche, ho trovato le risposte. Risposte, perché ci sono molte cose che possono impedire il caricamento lento in NHibernate.

  1. Query vs. session.Load: quando si recupera un elemento tramite session.Load () si ottiene un proxy. Ma non appena accedi a qualsiasi proprietà , diciamo il Url , l'oggetto viene recuperato includendo tutte le sue associazioni che non supportano il caricamento lazy.

  2. ref-proprietà: Il caricamento lento funziona solo su un ID oggetto. Quando un'associazione di proprietà viene risolta tramite una colonna diversa nell'entità target, NH la recupera avidamente. Non che ciò non sia possibile, semplicemente non è implementato: Bug

  3. non trovato = " ignora " consente non valido chiavi esterne, ovvero se l'entità referenziata non viene trovata NH avvierà la proprietà con nullo. NH non intercetta l'accesso alla proprietà per il caricamento lento, ma assegna invece un proxy oggetto. Con not-found = " ignore " non può decidere se la proprietà deve essere impostata su null o su un proxy per la chiave esterna, possibilmente non valida. Questo potrebbe essere risolto intercettando l'accesso alla proprietà.

  4. Quando si disabilita not-found = " ignora " e property-ref l'esportazione dello schema genererebbe vincoli che impongono un riferimento circolare. Non bene! La mappatura corretta sarebbe quindi una relazione uno a uno vincolata, in cui la chiave per HippoAccountSync deve avere un generatore foreign.

Risorse

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top