我们遇到NHibernate(版本4.0.0.4000和4.0.4.4000测试)返回重复结果的方式有问题。在下面的示例中,我得到566个结果(正确的数字结果),但只有549个是唯一的,这意味着有17个重复。
#region Get Record IDs
public IList<string> GetRecordIds(string user, string agency, DateTime utcFrom, DateTime utcTo, SearchDateRangeType dateRangeType, IEnumerable<string> status, IEnumerable<string> billingStatus, IEnumerable<string> qaStatus, IEnumerable<string> transmissionStatus, IEnumerable<string> scheduledTransmissions, int pageSize = -1, int pageNumber = -1)
{
using (ISession session = NHibernateHelper.OpenSession())
{
ICriteria crit = session.CreateCriteria<Metadata>();
var dateDisjunction = Restrictions.Disjunction();
dateDisjunction.Add(Restrictions.Between("IncidentDate", utcFrom, utcTo));
crit.Add(dateDisjunction);
if (string.IsNullOrEmpty(agency) == false)
{
crit.CreateAlias("Ownership._entities.AsIList", "entities");
crit.Add(Restrictions.Eq("entities._entityName._value", agency));
crit.Add(Restrictions.Eq("entities._isDeleted._value", false) || Restrictions.IsNull("entities._isDeleted._value"));
}
crit.AddOrder(Order.Asc(Projections.Property("RecordId")));
crit.SetProjection(Projections.Property("RecordId"));
if (pageSize > 0 && pageNumber > 0)
{
crit.SetFirstResult(pageSize * (pageNumber - 1)).SetMaxResults(pageSize);
}
var ret = crit.List<string>();
return ret;
}
}
#endregion
SQL Sample 1是NHibernate生成的第一次迭代代码。后续页面(第二页以后)使用ROW_NUMBER() OVER
。 SQL示例2是手动创建的第一页,它使用ROW_NUMBER() OVER
,就像它是后续页面一样。 NHibernate显然已经“优化”了第一页的ROW_NUMBER() OVER
,似乎(?)成为我们问题的原因。
SQL示例1:由NHibernate生成。造成重复。
SELECT
TOP (100) this_.RecordId as y0_
FROM
PcrMetadata this_
inner join
PcrEntities entities1_
on this_.Id=entities1_.ListKey
WHERE
(
this_.IncidentDate between '0001-01-01 00:00:00.0000000' and '9999-01-01 00:00:00.0000000'
)
and entities1_.Name = 'ClientIDNumber'
and (
entities1_.Entities_IsDeleted = 0
or entities1_.Entities_IsDeleted is null
)
SQL示例2:基于NHibernate第二页手动创建。不会造成重复。
SELECT
TOP (100) this_.RecordId as y0_
FROM
(SELECT
this_.Record as y0_,
ROW_NUMBER() OVER(
ORDER BY
CURRENT_TIMESTAMP) as __hibernate_sort_row
FROM
PcrMetadata this_
inner join
PcrEntities entities1_
on this_.Id=entities1_.ListKey
WHERE
(
this_.IncidentDate between '0001-01-01 00:00:00.0000000' and '9999-01-01 00:00:00.0000000'
)
and entities1_.Name = 'ClientIDNumber'
and (
entities1_.Entities_IsDeleted = 0
or entities1_.Entities_IsDeleted is null
)) as query
WHERE
query.__hibernate_sort_row > 0 -- CHANGE THIS NUMBER
我做错了吗?或者我有什么办法可以强迫NHibernate使用ROW_NUMBER? 在此先感谢您的帮助!
答案 0 :(得分:1)
我们无法加入集合并应用分页。因为我们正在获取cartesian product,这是分页(经验如上所述)。
我建议的解决方案是(我的方式永远)加入集合。为了得到类似的结果,我们应该:
关于此问题有detailed answer。
另见:
关于使结果与众不同的更多信息,但这在这里无济于事: