NHibernate RowCountInt64返回带有转换查询的错误计数

时间:2014-03-10 15:42:39

标签: nhibernate queryover nhibernate-3

我在执行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个。

任何想法如何解决这个问题?

2 个答案:

答案 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();