2009-10-29 22 views
9

Tengo un problema extraño en mi proyecto actual. La carga diferida para consultas no funciona. Cuando consulto una lista, nhibernate recupera todas las asociaciones por separado.NHibernate crea proxy a través de session.Load(), pero no a través de API de Criterios o de Linq

Extraje partes pequeñas de él y lo puse en una solución separada. Básicamente, lo que tengo ahora es un Account-Table y un AccountSync-Table. Ambos tienen una ID y una URL, mientras que la ID es solo un db-guid.

Mis clases son:

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

Cuando ahora me carga un objeto a través de su GUID:

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

... vuelve false y la propia cuenta es un proxy.

Pero cuando se carga una lista a través de la API de criterios:

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

... la propiedad Sync consigue inicializado (disparar una segunda consulta de selección), y el objeto devuelto no es un proxy.

¿Es ese comportamiento predeterminado? ¿Qué me estoy equivocando?

El mapeo es:

<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

no está seguro de si es del todo relacionados, pero hay problemas con not-found = "ignorar": http://nhjira.koah.net/browse/NH-1001 http: //guildsocial.web703 .discountasp.net/dasblogce/CommentView, guid, ba00b19d-bd60-442b-b2e7-935277a9f1eb.aspx –

+0

Tienes razón. Otro problema es la propiedad-ref: también deshabilita la carga diferida. http://maonet.wordpress.com/2007/12/05/lazy-load-conflicts-with-property-ref-in-many-to-one-mapping/ –

Respuesta

10

Después de bastante más investigación, encontré las respuestas. Respuestas, porque hay muchas cosas que pueden evitar la carga diferida en NHibernate.

  1. de consulta frente a Session.load: Cuando ir a buscar a través de un elemento session.Load() se obtiene un proxy. Pero tan pronto como acceda al cualquier propiedad, digamos Url, el objeto se obtiene incluyendo todas sus asociaciones que no admiten la carga diferida.

  2. property-ref: La carga lenta solo funciona sobre una identificación de objetos. Cuando una asociación de propiedades se resuelve a través de una columna diferente en la entidad objetivo, NH la busca ansiosamente. No es que esto no sería posible, es sólo de aplicación: Bug

  3. no encontrado = "Ignorar" permite claves externas no válidos, es decir, si la entidad hace referencia no se encuentra NH iniciará la propiedad con nulo. NH no intercepta el acceso a la propiedad para la carga diferida, sino que asigna un proxy de objeto. Con not-found="ignore" no puede decidir si la propiedad debe establecerse como nula o un proxy para la clave externa dada, posiblemente inválida. Esto podría resolverse interceptando el acceso a la propiedad.

  4. Al desactivar not-found="ignore" y property-ref la exportación de esquemas generaría restricciones que imponen una referencia circular. ¡No está bien! El mapeo correcto sería entonces una relación limitada de uno a uno, donde la clave para HippoAccountSync debe tener un generador foreign.

Recursos

+0

Con session.Load(), puede, por supuesto, acceda de forma segura a la propiedad Id del proxy sin tocar la base de datos, ya que primero le dio el ID al proxy. – Jay

+0

el enlace al error de propiedad-ref ya no existe, error 404. Alguna idea sobre este progreso? – shanabus

Cuestiones relacionadas