2010-07-08 6 views
3

Je requête suivante dans NHibernate où le résultat est une liste de DTO, pas des entités:SetCacheable jette IndexOutOfBoundsException

var result = query 
       //.SetCacheable(true) 
       .SetResultTransformer(new MyDTOTransformer()) 
       .List<DTO>(); 

Cela fonctionne avec SetCacheable en commentaire, mais il jette un IndexOutOfBoundsException quand je mets SetCacheable à true.

C'est le stacktrace:

at NHibernate.Type.TypeFactory.Disassemble(Object[] row, ICacheAssembler[] types, Boolean[] nonCacheable, ISessionImplementor session, Object owner) 
    at NHibernate.Cache.StandardQueryCache.Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, Boolean isNaturalKeyLookup, ISessionImplementor session) 
    at NHibernate.Loader.Loader.PutResultInQueryCache(ISessionImplementor session, QueryParameters queryParameters, IType[] resultTypes, IQueryCache queryCache, QueryKey key, IList result) 
    at NHibernate.Loader.Loader.ListUsingQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) 
    at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) 
    at NHibernate.Loader.Custom.CustomLoader.List(ISessionImplementor session, QueryParameters queryParameters) 
    at NHibernate.Impl.SessionImpl.ListCustomQuery(ICustomQuery customQuery, QueryParameters queryParameters, IList results) 
    at NHibernate.Impl.SessionImpl.List(NativeSQLQuerySpecification spec, QueryParameters queryParameters, IList results) 
    at NHibernate.Impl.SessionImpl.List[T](NativeSQLQuerySpecification spec, QueryParameters queryParameters) 
    at NHibernate.Impl.SqlQueryImpl.List[T]() 
    at ... 

Quelqu'un peut-il me aider et dire comment je peux résoudre ce problème (ou même si cela est pris en charge NHibernate)? J'utilise actuellement NHibernate-version 2.1.0.4000.

Merci, Jelle

+0

Avez-vous activé le cache de requête dans votre configuration? – AlexCuse

+0

J'ai mis use-query-cache à true (en utilisant fluent-nhibernate). Cependant, je n'ai pas spécifié de fournisseur de cache de second niveau. J'essaie seulement de réaliser que le résultat de ma requête nommée est mis en cache pendant ma session. – Jelle

Répondre

1

Je peux me tromper, mais je pense que le cache de requête repose sur le cache de second niveau étant activé. Pour être honnête, je me demande si cela serait très utile sans la mise en cache des entités dans le cache de second niveau, car tout ce qu'il stocke est une liste d'ID associée à une combinaison donnée de requête/paramètre (vous devez toujours aller à la base de données pour obtenir réellement les objets, et dans certaines situations cela pourrait conduire à 1 requête par objet).

This est l'un des meilleurs messages sur la mise en cache dans NHibernate que je l'ai vu, et il semble suggérer à la fin que vous ne pouvez requêtes de cache dans le cache de second niveau

0

j'eu cette même exception, et c'est réparé maintenant. Hier, lorsque j'ai utilisé un deuxième cache en définissant SetCacheable pour mon entité, un IndexOutOfBoundsException s'est produit.

J'ai recherché pour cela et trouvé un blog qui a mentionné qu'il peut être un problème avec mon Entité client. J'ai essayé query.setCacheable(true);, et ajouté query.setCacheMode(CacheMode.GET); et cela a fonctionné! Essayez cette solution.

0

Je pense que vous avez juste besoin de "déclarer" vos colonnes que vous renvoyez de votre DTO, en utilisant AddScalar. Sans les lignes AddScalar ci-dessous (une pour chacune des colonnes de votre jeu de résultats) il n'y a pas de métadonnées de définition de colonne dont le code de cache de second niveau a besoin (et donc l'exception hors limites d'index)

Utilisez simplement AddScalar pour lister toutes vos colonnes étant retourné et je parie que cela fonctionne.

var result = query 
      //.SetCacheable(true) 
      .AddScalar("yourfirstcolumn",NHibernateUtil.Int32) 
      .AddScalar("yoursecondcolumn",NHibernateUtil.String) 
      .SetResultTransformer(new MyDTOTransformer()) 
      .List<DTO>(); 
Questions connexes