linq 查询的 nhibernate 缓存问题
我从休眠缓存中看到一些奇怪的行为,并且无法理解其推理。我无法在执行以下选择操作时缓存查询,
query.Select(x=>x).ToList()
但可以在执行以下操作时缓存查询:
var query = session.Linq<Promoter>();
var p = query.ToList();
两者都会生成相同的 sql 查询,并且应该执行相同的操作。下面的测试解释了这个问题。
[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_
缓存是使用 Fluent 配置的:
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();
I am seeing some odd behavior from nhibernate caching and cannot understand the reasoning. I am not able to cache queries when doing select operations like
query.Select(x=>x).ToList()
but can cache when doing:
var query = session.Linq<Promoter>();
var p = query.ToList();
Both produce the same sql query and should be doign the same thing. The following test explains the problem.
[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();
}
}
My test results showing the hit on the db for the second query. queries 3 and 4 should not be hitting the 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_
The cache is configured using fluent:
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();
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用 .Select() 似乎有问题,如 .Select(x=>x) 由于某种原因,使用选择时会绕过缓存。任何其他语句都可以正常工作,例如 OrderBy()、Where() 等
示例代码如下:
Seems to be a problem with using .Select() as in .Select(x=>x) For some reason the cache is bypassed when using the select. Any other statements work fine like OrderBy(), Where() etc
Sample code below: