我在执行NHibernate查询时遇到了一个奇怪的错误。
我有一个IQueryOver<ExternalUser, ExternalUser>
类型的查询,它被过滤和转换(使用DistinctRootEntity,我猜这是导致问题)。我创建这样的查询:
List<Guid> companyList = /* some guids */
Company company = null;
var query = _session.QueryOver<ExternalUser>()
.JoinAlias(x => x.Companies, () => company)
.Where(() => company.Id.IsIn(companyList))
.TransformUsing(Transformers.DistinctRootEntity);
当我执行query.RowCountInt64()
时,我得到4。
当我执行query.List()
时,我会收到3件物品。
我也试过query.ToRowCountInt64Query().List<long>().Sum()
,这也给了我4个。
我也试过query.ToRowCountInt64Query().FutureValue<long>().Value
,这也给了我4个。
任何想法如何解决这个问题?
答案 0 :(得分:2)
我找到了一个有效的解决方案:
totalCount = query.Clone()
.Select(Projections.CountDistinct<User>(x => x.Id))
.SingleOrDefault<int>();
...但是我的解决方案限制我使用Int32,我并不满意。在我正在使用它的实现中它可能已经足够了,但是在其他地方可能存在需要很长时间的情况,所以任何其他建议都会受到赞赏。
修改强> 我上面的解决方案唯一不喜欢的是它返回了一个int,所以通过一些挖掘,我设法用另一个投影类修复它:
public class Int64CountProjection : CountProjection
{
protected internal Int64CountProjection(string prop) : base(prop) {}
protected internal Int64CountProjection(IProjection projection) : base(projection) {}
public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
{
return new IType[] { NHibernateUtil.Int64 };
}
public static CountProjection Distinct<T>(Expression<Func<T, object>> expression)
{
return new Int64CountProjection(ExpressionProcessor.FindMemberExpression(expression.Body)).SetDistinct();
}
}
...在这个课程中,我可以得到这样的计数(可以通过扩展方法进一步细化,但这对我来说已经足够了):
totalCount = query.Clone()
.Select(Int64CountProjection.Distinct<User>(x => x.Id))
.SingleOrDefault<long>();
编辑#2 我无法独自离开,所以我实施了一个扩展方法:
public static long CorrectRowCount<TRoot>(this IQueryOver<TRoot> query) where TRoot : IEntity
{
return query.Clone()
.Select(Int64CountProjection.Distinct<TRoot>(x => x.Id))
.ClearOrders()
.Skip(0)
.Take(RowSelection.NoValue)
.SingleOrDefault<long>();
}
答案 1 :(得分:0)
问题似乎是Transformers.DistinctRootEntity
很自然你会得到4个行数,3个列表。 DistinctRootEntity
在执行查询时重新运行4行并删除重复的内存。
您可以将query.RowCountInt64()
与正确的查询结合使用。
//
// Summary:
// Clones the QueryOver, removes orders and paging, and projects the row-count
// (Int64) for the query
IQueryOver<TRoot, TRoot> ToRowCountInt64Query();
//
// Summary:
// Short for ToRowCountInt64Query().SingleOrDefault<long>()
long RowCountInt64();