【发布时间】:2010-01-26 02:21:12
【问题描述】:
在 NHibernate 中使用公式定义计算属性时,如果公式根据查询限制改变其结果,特别是在查询缓存方面,这意味着什么?
更具体地说,考虑以下简单的 C# 类:
public class Entity
{
public Entity() { }
public virtual int Id { get; protected set; }
public virtual string Key { get; protected set; }
public virtual string Value { get; protected set; }
public virtual int Rank { get; protected set; }
}
使用以下简单的 NHibernate 映射进行映射:
<class name="Entity" mutable="false">
<id name="Id">
<generator class="native">
</id>
<property name="Key"/>
<property name="Value"/>
<property name="Rank" formula="row_number() over(order by value)">
</class>
使用会话工厂运行,hibernate.cache.use_query_cache 选项设置为true,并通过以下方式查询:
ICriteria criteria = session.CreateCriteria(typeof(Entity));
criteria.SetCacheable(true);
criteria.SetCacheRegion("SearchResults");
IList<Entity> queryResult1 = criteria.List<Entity>();
criteria = session.CreateCriteria(typeof(Entity));
criteria.SetCacheable(true);
criteria.SetCacheRegion("SearchResults");
criteria.Add(Restrictions.Like("Key", "a", MatchMode.Anywhere));
IList<Entity> queryResult2 = criteria.List<Entity>();
Entity directResult = session.Load<Entity>(id);
NHibernate 会以合理的方式处理返回的实体吗?或者,一个缓存查询的“Rank”值是否会由于查询缓存而污染另一个查询的 Rank 值?在 NHibernate 映射中使用这样的公式时是否还有其他问题?
编辑:
还可能值得注意的是,在我的特定情况下,“实体”不是一流的业务实体,而是一种元实体。它映射到其他一流实体的索引数据库视图,并专门用于搜索(session.Load(id) 调用是人为设计的,实际上不应该发生)。
而且,如果我怀疑缓存对缓存有影响,那么类似的用例可能存在哪些替代方案来避免潜在问题?
【问题讨论】:
-
不是您问题的答案,但您可能想查看 NHibernate.Lucene。这更容易实现,并且以您尝试的方式进行搜索的执行速度更快。
-
此示例仅用于说明问题。我们实际上正在使用 SQL Server 的全文搜索,如果/当我们遇到功能或可伸缩性限制时,Lucene 将在评估列表的顶部。
-
Rank 属性并不是实体上真正的持久值 - 它是实体在执行的特定查询中返回的结果。恕我直言,将它放在您的域类上是不对的。而且您还可以在单个会话中获取查询,相互“干扰”(或如您所说的那样相互“污染”)。
-
明白了——这就是问题所在。您能否详细说明答案中的潜在问题(而不是评论),甚至可能提供替代建议以更好地处理检索此类数据? (注意:已编辑问题以提供有关用例的更多详细信息)
标签: sql-server nhibernate calculated-columns rank