2012-10-26 97 views
0

我有一张表格,里面存储着使用NHibernate从我的web应用程序中查询的分层数据。这是很简单的在NHibernate中缓存公用表表达式(CTE)查询

CREATE TABLE [dbo].[Relationships](
    [RelationshipId] [uniqueidentifier] NOT NULL, 
    [ParentId] [uniqueidentifier] NULL, 
    [ParentTypeId] [uniqueidentifier] NULL, 
    [ChildId] [uniqueidentifier] NOT NULL, 
    [ChildTypeId] [uniqueidentifier] NOT NULL 
) 

我们查询从该表中我使用SQL Server的一个特征信息(2005年以来)称为公用表表达式,或者CTE的简称。它可以让我编写递归查询,这对上表中的表格非常有用。现在

WITH Ancestors(RelationshipId, ParentId, ChildId) 
AS 
(
    SELECT r.RelationshipId, r.ParentId, r.ChildId 
     FROM Relationships r 
     WHERE ChildId = :objectId 
    UNION ALL 
    SELECT r.RelationshipId, r.ParentId, r.ChildId 
     FROM Relationships r 
      INNER JOIN Ancestors 
       ON Ancestors.ParentId = r.ChildId 
) 
SELECT RelationshipId, ParentId, ChildId FROM Ancestors 

,这是伟大的表现并不坏,但是当我尝试使用它来确定祖先往上走的树,或者更糟,使用类似的查询,以确定decendants可以征税。

现在我想简单地缓存这个查询的结果,但是如果我有.SetCacheable(true),我得到nHibernate Index was outside the bounds of the array.的错误。如果我删除缓存支持查询工作正常。

查询工作正常,如果我从我的电话中删除缓存支持Session.CreateSQLQuery()现在我已经在线寻找尝试找到一个原因,但我没有找到我发现的结果中的共识。

所以,虽然我很好奇为什么它不起作用,我更感兴趣的是寻找一种解决方法,让缓存与我的CTE在nHibernate中一起工作?

回答

0

结束简单地做了以下事情。我还没有测试过缓存,但我可能不得不牺牲那些有利于CTE提供的灵活性。

const string query = "WITH Ancestors(RelationshipId, ParentId, ChildId) " + 
         "AS " + 
         "(SELECT por.RelationshipId, por.ParentId, por.ChildId " + 
         "FROM PseudoObjectRelationships por WHERE ChildId = :objectId " + 
         "UNION ALL " + 
         "SELECT por.RelationshipId, por.ParentId, por.ChildId " + 
         "FROM PseudoObjectRelationships por " + 
         "INNER JOIN Ancestors " + 
         "ON Ancestors.ParentId = por.ChildId " + 
         ") " + 
         "SELECT RelationshipId, ParentId, ChildId FROM Ancestors"; 

return ((DynamicObjectRepository<TObject>)dynamicObjectRepository).CreateSQLQuery(query) 
     .SetGuid("objectId", objectId) 
     .SetResultTransformer(Transformers.AliasToBean<Relationship>()) 
     .List<Relationship>(); 
0

我可以看到有关错误的更多详细信息,但我会说你可以使用命名查询来代替... http://geekswithblogs.net/TStewartDev/archive/2010/04/11/caching-nhibernate -named-queries.aspx

在XML中定义SQL(如果需要,调用SP),然后声明结果集。您正在告诉nhibernate从该调用中期望得到什么,所以我认为它可以解决如何缓存它(猜测)。我通常转变为dto。

要小心,如果Db发生变化,您需要手动清除缓存。您没有使用实体,因此如果底层数据发生更改,您必须自行清除缓存。