2017-06-28 8 views
1

je le scénario suivant:NHibernate: Éviter N + 1 Problèmes lors de la classe de base est utilisée dans la cartographie

Session classe a beaucoup ProcessableItem s et un SqlTask est dérivé de ProcessableItem classe. Un SqlTask peut avoir plusieurs variables (propriété SqlTaskInputParameters, SqlParameterVariable classe, certaines tâches n'ont pas de variables).

Le point est dans la classe Session la ProcessableItem (pas la tâche elle-même) est utilisé comme propriété de navigation:

public class Session 
{ 
    [DataMember] 
    public virtual IList<ProcessableItem> ProcessableItems 
    { 
     get { return this._items; } 
     set { this._items = value; } 
    }  
} 

public SessionMap() 
{ 
    HasMany(t => t.ProcessableItems) 
} 

public class ProcessableItem 
{ 
    ... 
} 

public class SqlTask : ProcessableItem 
{ 
    [DataMember] 
    public virtual IList<SqlParameterVariable> SqlTaskInputParameters { get; set; }; 
} 

Donc, dans ce scénario, la classe de base ProcessableItem est utilisée comme propriété de navigation et je veux hâte chargez les objets variables de SqlTask afin d'éviter le problème n + 1.

Voici le code que j'ai, mais comment puis-je accéder à des propriétés spécifiques du dérivé SqlTask (comme SqlTaskInputParameters):

var query = session.Query<ETLSession>() 
        .Where(s => s.Id == request.IdETLSession); 
query.FetchMany(s => s.ProcessableItems) 
       .ThenFetch(p => p.ChildsOnSuccess).ToFuture(); 
Session session = query.ToFuture().ToList().First(); 

Répondre

1

Vous ne pouvez pas les relations de charge désireux de classe dérivée.

Dans votre cas, vous ne devriez même pas, car vous semblez déjà aller chercher une autre collection (ChildsOnSuccess), et en extraire une autre ici provoquerait un produit cartésien entre eux, entraînant la duplication de vos résultats. (Ceci est une limitation de NHibernate.)

Les bonnes nouvelles sont, il y a d'autres manières qu'allant chercher ardemment pour résoudre le problème N + 1.

  • Conserver le chargement paresseux mais activer batching of lazy loads. J'ai mis quelques explications détaillées here on Stack Overflow.
  • Utiliser second level cache. Mais bon, c'est la mise en cache, donc mieux vaut commencer par l'autre, ce qui sera quand même utile si vous ajoutez un cache de second niveau plus tard.