0

我有一个表格,其中包含我正在使用 NHibernate 从我的网络应用程序中查询的分层数据。这很简单

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 年以来)的一项功能,称为 Common Table Expressions,或简称为 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

现在,这很好,性能也不错,但是当我尝试使用它来确定上树的祖先,或者更糟糕的是,使用类似的查询来确定后代时,它可能会很费力。

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

如果我从对Session.CreateSQLQuery()Now 的调用中删除缓存支持,则查询工作正常。

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

4

2 回答 2

0

我可以查看错误的更多详细信息,但我会说您可以改用命名查询... http://geekswithblogs.net/TStewartDev/archive/2010/04/11/caching-nhibernate-named-queries .aspx

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

请注意,如果 Db 发生更改,您将需要手动清除缓存。您没有使用实体,因此如果基础数据发生更改,您必须自己清除缓存。

于 2012-10-28T00:04:11.737 回答
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>();
于 2012-11-29T00:39:56.920 回答