Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
即使ORDER BY子句不同,NHibernate也会检索缓存的查询结果_Nhibernate_Sql Order By_Query Cache - Fatal编程技术网

即使ORDER BY子句不同,NHibernate也会检索缓存的查询结果

即使ORDER BY子句不同,NHibernate也会检索缓存的查询结果,nhibernate,sql-order-by,query-cache,Nhibernate,Sql Order By,Query Cache,我看到了NHibernate中的一个bug,它带有查询缓存和ORDERBY子句 当我运行以下查询时 SELECT this_.Id as y0_, this_.Name as y1_ FROM Products this_ WHERE this_.IsActive = 1 ORDER BY this_.IsPremium desc 。。。如果我打开了查询缓存,并告诉NHibernate缓存此查询(使用例如条件.SetCacheable(tru

我看到了NHibernate中的一个bug,它带有查询缓存和ORDERBY子句

当我运行以下查询时

SELECT this_.Id          as y0_,
       this_.Name        as y1_
FROM   Products this_
WHERE  this_.IsActive = 1
ORDER BY this_.IsPremium desc
。。。如果我打开了查询缓存,并告诉NHibernate缓存此查询(使用例如
条件.SetCacheable(true)
),则NHibernate会成功缓存其结果

不幸的是,正如Wonder告诉我的,NHibernate在运行此查询时也使用缓存的查询结果:

SELECT this_.Id          as y0_,
       this_.Name        as y1_
FROM   Products this_
WHERE  this_.IsActive = 1
ORDER BY this_.IsPremium desc,
         this_.Name

有人能解释一下为什么或者给我指一些关于这个“特性”的深入文档吗?或者,更好的是,是否有人有解决该问题的解决方案?

NHibernate使用一级缓存(通过身份映射实现)来缓存您查询的每个对象。NHibernate处理单个实体,即使查询对象列表也是如此

让我解释一下:
您查询是否执行此查询并尝试获取id为1的实体:

session.get<SomeEntity>(1);
session.get(1);
NHibernate将检查缓存,看看它是否已经包含id 1。如果是这样,缓存对象将被返回,并且它不会运行查询。如果没有,则选择记录执行查询,将其放入缓存并返回给您。如果您再次执行查询,它将被缓存,并且对象将在不使用新查询的情况下返回

现在,如果您查询如下列表:

session.QueryOver<SomeEntity>().List();
session.QueryOver().List();
nhibernate不知道将获取哪个id,因此它将查询所有记录并逐个检查缓存中的结果,即使您运行了两次查询。假设数据库中有2条记录(id 1和2)。当缓存仍然为空时,使用查询获取它们。这两条记录都会被提取、放入缓存并返回给您。现在,插入记录3、4和5,在执行此操作时,还将更新记录1。现在,如果再次运行查询,它将读取所有5条记录,但现在还将缓存记录3、4和5。您将得到一个包含5个对象的列表,其中3、4、5是刚读取的对象,但返回缓存版本的1和2。您将无法获得id 1的更新版本

因此,回答您的问题:通过更改顺序并不重要。您的查询将生成一组记录,这些记录将逐个根据缓存进行检查,如果其中一个记录已经存在,则返回该缓存版本

您的问题的解决方案可能是:

  • 使用session.Refresh(obj);如果您知道哪些已更新
  • 从会话中逐出部分或所有实体(这意味着它们将被抛出缓存,并可以通过查询重新蚀刻)。注意:如果您将其逐出,更改的内容将不会保存
  • 您可以使用无状态会话,正如无状态名称所示,它没有缓存
NHibernate使用一级缓存(通过身份映射实现)来缓存您查询的每个对象。NHibernate处理单个实体,即使查询对象列表也是如此

让我解释一下:
您可以查询是否执行此查询并尝试获取id为1的实体:

session.get<SomeEntity>(1);
session.get(1);
NHibernate将检查缓存,以查看它是否已经包含id 1。如果是这样,缓存对象将被返回,并且它不会运行查询。如果没有,则选择记录执行查询,将其放入缓存并返回给您。如果您再次执行查询,它将被缓存,并且对象将在不使用新查询的情况下返回

现在,如果您查询如下列表:

session.QueryOver<SomeEntity>().List();
session.QueryOver().List();
nhibernate不知道将获取哪个id,因此它将查询所有记录并逐个检查缓存中的结果,即使您运行了两次查询。假设数据库中有2条记录(id 1和2)。当缓存仍然为空时,使用查询获取它们。这两条记录都会被提取、放入缓存并返回给您。现在,插入记录3、4和5,在执行此操作时,还将更新记录1。现在,如果再次运行查询,它将读取所有5条记录,但现在还将缓存记录3、4和5。您将得到一个包含5个对象的列表,其中3、4、5是刚读取的对象,但返回缓存版本的1和2。您将无法获得id 1的更新版本

因此,回答您的问题:通过更改顺序并不重要。您的查询将生成一组记录,这些记录将逐个根据缓存进行检查,如果其中一个记录已经存在,则返回该缓存版本

您的问题的解决方案可能是:

  • 使用session.Refresh(obj);如果您知道哪些已更新
  • 从会话中逐出部分或所有实体(这意味着它们将被抛出缓存,并可以通过查询重新蚀刻)。注意:如果您将其逐出,更改的内容将不会保存
  • 您可以使用无状态会话,正如无状态名称所示,它没有缓存
setcacable用于二级缓存目的。您正在使用二级缓存吗?我猜您只使用由标识映射实现的一级缓存。setcacable用于二级缓存目的。您正在使用二级缓存吗?我猜您只使用由身份映射实现的一级缓存。