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。

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

4

2 回答 2

3

我找到了一个可行的解决方案:

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>();
     }
于 2014-03-10T16:34:42.010 回答
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();
于 2014-03-10T18:07:37.600 回答