Question

J'ai une table Parent et une table Child. Child contient une clé étrangère dans la table Parent, créant une relation un à plusieurs. Voici une partie de ma cartographie que je définis avec NHibernate couramment:

public class ParentMap : ClassMap<Parent>
{
    public ParentMap()
    {
        WithTable("Parents");

        Id(x => x.Id, "ParentID")
        .WithUnsavedValue(0)
        .GeneratedBy.Identity();

        Map(x => x.Description, "Description");

        HasMany<Child>(x => x.Childs)
        .LazyLoad()
        .WithKeyColumn("ParentID")
        .IsInverse()
        .AsSet();
    }
}

public class ChildMap : ClassMap<Child>
{
    public ChildMap()
    {
        WithTable("Childs");

        Id(x => x.Id, "ChildID")
        .WithUnsavedValue(0)
        .GeneratedBy.Identity();

        References(x => x.Parent, "ParentID")
            .CanNotBeNull()
            .LazyLoad();
    }
}

Comme vous pouvez le constater, j'ai défini LazyLoad sur la relation. Notez également que dans mes classes de modèle, toutes les propriétés sont définies comme virtuelles.

Maintenant pour la requête simple:

ICriteria crit = Session.CreateCriteria(typeof(Child))
    .Add(Expression.Eq("Id", 18));
IList<Child> list = crit.List<Child>();

Et le SQL généré:

SELECT this_.ChildID            as ChildID5_1_,
       this_.ParentID           as ParentID5_1_,
       parent2_.ParentID    as ParentID4_0_,
       parent2_.Description as Descript2_4_0_
FROM   Childs this_
       inner join Parents parent2_
         on this_.ParentID = parent2_.ParentID
WHERE  this_.ChildID = 18 /* @p0 */

Comme vous pouvez le constater, il effectue une jointure sur la table parent et sélectionne ses champs (id et description). Mais pourquoi fait-il cela depuis que j'ai demandé du lazyloading?

Maintenant si je change la requête en:

ICriteria crit2 = Session.CreateCriteria(typeof(Child))
    .SetFetchMode("Parent", FetchMode.Lazy)
    .Add(Expression.Eq("Id", 18));

Deux requêtes SQL ont été générées:

SELECT this_.ChildID  as ChildID5_0_,
       this_.ParentID as ParentID5_0_
FROM   Childs this_
WHERE  this_.ChildID = 18 /* @p0 */

ce qui est bon pour moi: pas de jointure, la table Parent n’est pas interrogée. Mais je reçois aussi le second:

SELECT parent0_.ParentID    as ParentID4_0_,
       parent0_.Description as Descript2_4_0_
FROM   Parents parent0_
WHERE  parent0_.ParentID = 45 /* @p0 */

qui interroge à nouveau la table parent.

Ces 2 requêtes sont générées pendant la ligne:

IList<Child> list = crit.List<Child>();

Je suis totalement ignorant de ce qui se passe ici. Quelqu'un peut-il aider?

Était-ce utile?

La solution

Cela dépend de votre version de Fluent NHibernate. Jusqu'à un certain point, il était par défaut que toutes les entités ne ne soient pas chargées paresseuses. Cela équivaut à définir explicitement lazy="false" dans votre entité. Ce n'est plus le cas, mais si vous utilisez une version antérieure à cette étape, vous constaterez ce problème.

Le paramètre de chargement paresseux plusieurs-à-un / références est remplacé par le chargement paresseux au niveau de l'entité depuis la cible. Par conséquent, si vous utilisez cette ancienne version de FNH, le paramètre d'entité rendra votre References(...).LazyLoad() appel moot .

Vous devez vérifier que vous utilisez la dernière version de FNH, ce qui devrait résoudre le problème. Cependant, si ce n'est pas le cas, vous devez définir explicitement le chargement différé dans votre entité Parent. Vous pouvez le faire avec la méthode LazyLoad sur le ClassMap<T>.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top