开发者

NHibernate Paged Results & Incorrect Row Count

开发者 https://www.devze.com 2023-02-15 21:05 出处:网络
I have a model called \'BusinessPage\' which can be associated with 1 or more \'BusinessPageCategories\'. So I\'ve got a 3rd table called \'BusinessPagesInCategories\' that links these two.

I have a model called 'BusinessPage' which can be associated with 1 or more 'BusinessPageCategories'. So I've got a 3rd table called 'BusinessPagesInCategories' that links these two.

I am trying to get a paged recordset of BusinessPages, along with the total number of records (I may have 100 rows in total but only return 20 at a time, but I pass back an int containing that total number in addition to the 20 rows).

The problem I have is that, since I implemented the Many-To-Many relationship, it was bringing back the same BusinessPage row x times (where x is the number of categories that BusinessPage is associated with). I only want a single instance of each business page to be returned. So I added the following to my NHibernate Criteria to give Distinct BusinessPage results.

.SetResultTransformer(CriteriaSpecification.DistinctRootEntity);

Whilst this works for me, in that I'm now correctly getting a single row per BusinessPage (and my Categories property within each BusinessPage contains the correct x categories that it's assigned to), my row count is not reflecting that 'distinct' count - instead, if I have just 1 BusinessPage record which is associated with 3 categories, the row count is 3!?!

BusinessPage (Model)

public virtual int BusinessPageId { get; private set; }
public virtual IList<BusinessPageCategory> Categories { get; set; }
public virtual string BusinessName { get; set; }

BusinessPageCategory (Model)

public virtual int CategoryId { get; private set; }
public virtual string CategoryName { get; set; }

BusinessPagesInCategories (SQL Table used to relate the two models)

BusinessPageId
CategoryId

Here is the code I use to get my 'paged business pages':

public virtual IList<BusinessPage> GetPagedBusinessPages(int pageNumber, int pageSize, out int totalRecordCount)
{
    ICriteria c = CreateCriteria_BusinessPage()

开发者_如何学编程        // we only want distinct business pages returned
        .SetResultTransformer(CriteriaSpecification.DistinctRootEntity);

    return c.PagedResults<BusinessPage>(pageNumber, pageSize, out totalRecordCount);
}

protected virtual ICriteria CreateCriteria_BusinessPage()
{
    return Session
        .CreateCriteria<BusinessPage>()
        .AddOrder(Order.Asc("BusinessName"));
}

And here are my extension methods for getting both the paged results AND the all important row count.

public static IList<T> PagedResults<T>(this ICriteria criteria, int pageNumber, int pageSize, out int totalRecordCount)
{
    var results = criteria
        .CloneNewCriteria()
        .SetPaging(pageNumber, pageSize)
        .Future<T>();

        totalRecordCount = criteria.GetTotalCount().Value;

        return results.ToList<T>();
}

public static ICriteria CloneNewCriteria(this ICriteria criteria)
{
    return CriteriaTransformer.Clone(criteria);
}

public static ICriteria SetPaging(this ICriteria criteria, int pageNumber, int pageSize)
{
    return criteria
        .SetMaxResults(pageSize)
        .SetFirstResult((pageNumber - 1) * pageSize);
}

public static IFutureValue<int> GetTotalCount(this ICriteria criteria)
{
    criteria.ClearOrders();

    return criteria
        .SetProjection(Projections.RowCount())
        .FutureValue<int>();
}

I'm still very new to NHibernate so there may be a simple solution to this?


Problem solved. It turns out that I was setting up an Alias to the Categories regardless of whether I need to filter by category or not, therefore, the join was established in a scenario I didn't need it to be, and as a result was bringing back the duplicate rows (one for each join onto the categories)!

In the scenario whereby I do need to pass in a categoryid and filter my results on that category, there are no duplicate rows via the joins as each businesspage can be assigned any 1 category just the once.

I thought it was strange that it was making this join to categories even though I wasn't wanting to reference the categories object until after I had the initial records returned, but it looks like creating that alias outside of the scope required, forced the join and the loading of those categories unnecessarily.

0

精彩评论

暂无评论...
验证码 换一张
取 消