我有一个表,其中包含我使用NHibernate从我的Web应用程序查询的分层数据。这很直接
CREATE TABLE [dbo].[Relationships](
[RelationshipId] [uniqueidentifier] NOT NULL,
[ParentId] [uniqueidentifier] NULL,
[ParentTypeId] [uniqueidentifier] NULL,
[ChildId] [uniqueidentifier] NOT NULL,
[ChildTypeId] [uniqueidentifier] NOT NULL
)
现在从这个表中查询信息我正在使用一个名为Common Table Expressions的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
现在,这很好,而且性能并不差,但是当我尝试使用它来确定祖先上升树时,或者更糟糕的是,使用类似的查询来确定后代时,它可能会很费力。
现在我想简单地缓存此查询的结果,但如果我有Index was outside the bounds of the array.
,我会收到来自nHibernate .SetCacheable(true)
的错误。如果我删除缓存支持,查询工作正常。
如果我从Session.CreateSQLQuery()
调用中删除缓存支持,查询工作正常。现在我已经在网上尝试查找原因但我在找到的结果中没有找到共识。
因此,虽然我很好奇为什么它不起作用,但我更感兴趣的是找到一种解决方法来让缓存在nHibernate中使用我的CTE?
答案 0 :(得分:0)
我可以看到错误的更多详细信息,但我会说你可以使用命名查询而不是... http://geekswithblogs.net/TStewartDev/archive/2010/04/11/caching-nhibernate-命名queries.aspx
在XML中定义SQL(如果需要,调用SP),然后声明Resultset。你告诉nhibernate从调用中得到什么,所以我认为它可以解决如何缓存它(猜测)。我通常转变为dto。
注意,如果Db发生变化,您需要手动清除缓存。您没有使用实体,因此如果基础数据已更改,您必须自己清除缓存。
答案 1 :(得分: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>();