2010-02-28 55 views
5

我看到一些来自nhibernate缓存的奇怪行为,无法理解推理。做选择操作像nhibernate缓存linq查询问题

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

当我不能够缓存查询,但这样做的时候可以缓存:

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

都产生相同的SQL查询,并应doign同样的事情。以下测试解释了这个问题。

[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(); 
     } 
    } 

我的测试结果显示第二个查询的数据库命中。查询3和4不应该被击中分贝:

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_ 

高速缓存被使用流利配置:

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(); 

回答

2

似乎与使用。选择()作为在。选择(X A =问题> x)由于某些原因,在使用select时缓存被绕过。任何其他语句做工精细喜欢的OrderBy(),其中()等

示例代码如下:

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 
      }