2010-02-28 720 views
5

Estoy viendo un comportamiento extraño de caché de nhibernate y no puedo entender el razonamiento. No soy capaz de almacenar en caché las consultas al hacer operaciones de selección comoproblema de caché de nhibernate con consultas de linq

query.Select(x=>x).ToList() 

pero puedo almacenar en caché cuando se hace:

var query = session.Linq<Promoter>(); 
var p = query.ToList(); 

Ambos producen la misma consulta SQL y debe ser doign la misma cosa. La siguiente prueba explica el problema.

[Test] 
    public void Can_Use_Cache() 
    { 
     ISessionFactory factory = Storage.Application.Get<ISessionFactory>("SessionFactory"); 
     // initial hit on the database and load into cache - all fine 
     using (var session = factory.OpenSession()) 
     { 
      Console.WriteLine(""); 
      Console.WriteLine("First Query"); 
      var query = session.Linq<Promoter>(); 
      query.QueryOptions.SetCachable(true); 
      query.QueryOptions.SetCacheMode(CacheMode.Normal); 
      var p = query.ToList(); 
     } 
     // no hit on the database and retrieved from cache as expected - all fine 
     using (var session = factory.OpenSession()) 
     { 
      Console.WriteLine(""); 
      Console.WriteLine("Second Query"); 
      var query = session.Linq<Promoter>(); 
      query.QueryOptions.SetCachable(true); 
      query.QueryOptions.SetCacheMode(CacheMode.Normal); 
      var p = query.ToList(); 
     } 
     // hits the db - should have come from the cache - not working 
     using (var session = factory.OpenSession()) 
     { 
      Console.WriteLine(""); 
      Console.WriteLine("Third Query"); 
      var query = session.Linq<Promoter>(); 
      query.QueryOptions.SetCachable(true); 
      query.QueryOptions.SetCacheMode(CacheMode.Normal); 
      var p = query.Select(x=>x).ToList(); 
     } 
     // hits the db again - should have come from the cache - again not working 
     using (var session = factory.OpenSession()) 
     { 
      Console.WriteLine(""); 
      Console.WriteLine("Fourth Query"); 
      var query = session.Linq<Promoter>(); 
      query.QueryOptions.SetCachable(true); 
      query.QueryOptions.SetCacheMode(CacheMode.Normal); 
      var p = query.Select(x => x).ToList(); 
     } 
    } 

Mis resultados de la prueba que muestran el golpe en la base de datos para la segunda consulta. consultas 3 y 4 no debe golpear la db:

2010-02-28 12:05:23,046 INFO Started Logging 

First Query 
2010-02-28 12:05:23,156 DEBUG SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 
NHibernate: SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 

Second Query 

Third Query 
2010-02-28 12:05:23,315 DEBUG SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 
NHibernate: SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 

Fourth Query 
2010-02-28 12:05:23,318 DEBUG SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 
NHibernate: SELECT this_.Id as Id11_0_, this_.Version as Version11_0_, this_.Name as Name11_0_ FROM Promoters this_ 

La memoria caché se configura utilizando fluidez:

SessionFactory = Fluently.Configure() 
      .Database(MsSqlConfiguration.MsSql2008 
          .ConnectionString(ConfigurationService.SqlConnectionString) 
          .ShowSql() 
         .Cache(c => c 

            .UseQueryCache() 
            .ProviderClass(typeof(NHibernate.Cache.HashtableCacheProvider).AssemblyQualifiedName)) 
         ) 
      .Mappings(m => m.FluentMappings.AddFromAssemblyOf<EventMap>() 
           .Conventions.Setup(MappingConventions.GetConventions())) 
      .ExposeConfiguration(BuildSchema) 
      .BuildSessionFactory(); 

Respuesta

2

parece ser un problema con el uso .Seleccionar() como en .Seleccionar (x = > x) Por alguna razón, la memoria caché se pasa por alto al usar la selección. Cualquier otra declaración funcionan bien como OrdenarPor(), donde(), etc

código de ejemplo siguiente:

using (var session = factory.OpenSession()) 
      { 
       Console.WriteLine(""); 
       var query = session.Linq<Promoter>(); 
       query.QueryOptions.SetCachable(true); 
       query.QueryOptions.SetCacheMode(CacheMode.Normal); 
       var p = query.OrderBy(x => x.Name).ToList();// works fine 
       //var p = query.OrderBy(x => x.Name).Select(x=>x).ToList();// will hit the db 
      } 
Cuestiones relacionadas