1

次のような ICriteria クエリがあります。

var contentCriteria = DetachedCriteria.For<InvoiceItem>();
var countCriteria = DetachedCriteria.For<InvoiceItem>();

if (model.CurrentPage <= 0) model.CurrentPage = 1;

if (model.OnlyShowErrors)
{
    contentCriteria.Add(Restrictions.Not(Restrictions.Eq("TroubleClass", TroubleClasses.Success)));
    countCriteria.Add(Restrictions.Not(Restrictions.Eq("TroubleClass", TroubleClasses.Success)));
}

if (!string.IsNullOrEmpty(model.BatchId))
{
    contentCriteria.Add(Restrictions.Eq("BatchId", model.BatchId));
    countCriteria.Add(Restrictions.Eq("BatchId", model.BatchId));
}

if (model.DocumentStartDate != null)
{
    contentCriteria.Add(Restrictions.Ge("DocumentDate", model.DocumentStartDate));
    countCriteria.Add(Restrictions.Ge("DocumentDate", model.DocumentStartDate));
}

if (model.DocumentEndDate != null)
{
    contentCriteria.Add(Restrictions.Le("DocumentDate", model.DocumentEndDate));
    countCriteria.Add(Restrictions.Le("DocumentDate", model.DocumentEndDate));
}

if (!string.IsNullOrEmpty(model.VendorId))
{
    contentCriteria.Add(Restrictions.Eq("VendorId", model.VendorId));
    countCriteria.Add(Restrictions.Eq("VendorId", model.VendorId));
}


using (var session = GetSession())
{

    var countC = countCriteria.GetExecutableCriteria(session)
        .SetProjection(Projections.CountDistinct("RecordId"));

    var contentC = contentCriteria
        .AddOrder(Order.Desc("PersistedTimeStamp"))
        .GetExecutableCriteria(session)
        .SetResultTransformer(Transformers.DistinctRootEntity)
        .SetFirstResult((model.CurrentPage * model.ItemsPerPage) - model.ItemsPerPage)
        .SetMaxResults(model.ItemsPerPage);

    var mq = session.CreateMultiCriteria()
        .Add("total", countC)
        .Add<InvoiceItem>("paged", contentC);

    model.Invoices = ((IEnumerable<InvoiceItem>)mq.GetResult("paged"));
    model.Invoices = model.Invoices
        .OrderBy(x => x.PersistedTimeStamp);

    model.TotalItems = (int)(mq.GetResult("total") as System.Collections.ArrayList)[0];
}
return model;

これにより結果が返されますが、結果が のグループになると予想される場合はmodel.ItemsPerPage、めったにありません。.SetResultTransformer(Transformers.DistinctRootEntity)制限を超えて変換が実行されていると思いますが、その.SetMaxResults(model.ItemsPerPage)理由や修正方法がわかりません。誰かが私を啓発してもらえますか?

4

2 に答える 2

0

したがって、これはこのブログ投稿に書かれていることと直接関連しています。さらに、PostgreSQL が SELECT リストにないものによって順序付けられた DISTINCT 順序付けセットを許可しないという、プラットフォーム固有の問題がありました。最終的に、次のように、データベースに対して 2 つの呼び出しを行う必要がありました。

using (var session = GetSession())
{
    //I honestly hope I never have to reverse engineer this mess.  Pagination in NHibernate
    //when ordering by an additional column is a nightmare.
    var countC = countCriteria.GetExecutableCriteria(session)
        .SetProjection(Projections.CountDistinct("RecordId"));

    var contentOrdered = contentCriteria
        .SetProjection(Projections.Distinct(
            Projections.ProjectionList()
                .Add(Projections.Id())
                .Add(Projections.Property("PersistedTimeStamp"))
                ))
        .AddOrder(Order.Desc("PersistedTimeStamp"))
        .SetFirstResult((model.CurrentPage * model.ItemsPerPage) - model.ItemsPerPage)
        .SetMaxResults(model.ItemsPerPage);

    var contentIds = contentOrdered.GetExecutableCriteria(session)
        .List().OfType<IEnumerable<object>>()
        .Select(s => (Guid)s.First())
        .ToList();

    var contentC = DetachedCriteria.For<InvoiceItem>()
        .Add(Restrictions.In("RecordId", contentIds))
        .SetResultTransformer(Transformers.DistinctRootEntity);

    var mq = session.CreateMultiCriteria()
        .Add("total", countC)
        .Add("paged", contentC);

    model.Invoices = (mq.GetResult("paged") as System.Collections.ArrayList)
        .OfType<InvoiceItem>()
        .OrderBy(x => x.PersistedTimeStamp);

    model.TotalItems = (int)(mq.GetResult("total") as System.Collections.ArrayList)[0];
}
return model;

これはきれいではありませんが、うまくいきました。NHibernate の人々はこれに取り組み、少し簡単にする必要があると思います。

于 2012-08-21T18:36:57.720 に答える
0

これは本質的に NHibernate のバグではなく、ROWNUMDISTINCTが一緒に適用された場合の SQL クエリの動作であるため、NHibernate によって生成された SQL を確認する必要があります。これは、以前から既知の問題リストに含まれていた問題です。

次の URL はあなたを啓発するかもしれません...

行番号と DISTINCT

ROWNUM の仕組み

于 2012-08-21T17:51:59.650 に答える