Проблема с nHibernate Distinct и пейджингом

У меня есть этот метод репозитория, который использует API QueryOver

    public IList<Message> ListMessagesBy(string text, IList<Tag> tags, int pageIndex, out int count, out int pageSize)
    {
        pageSize = 10;
        var likeString = string.Format("%{0}%", text);
        var query = session.QueryOver<Message>()
            .Where(Restrictions.On<Message>(m => m.Text).IsLike(likeString) ||
            Restrictions.On<Message>(m => m.Fullname).IsLike(likeString));

        if (tags.Count > 0)
        {
            var tagIds = tags.Select(t => t.Id).ToList();
            query
                .JoinQueryOver<Tag>(m => m.Tags)
                .WhereRestrictionOn(t => t.Id).IsInG(tagIds)
                .TransformUsing(Transformers.DistinctRootEntity);
        }                        

        count = 0;
        if(pageIndex < 0)
        {
            count = query.ToRowCountQuery().FutureValue<int>().Value;
            pageIndex = 0;
        }
        return query.OrderBy(m => m.Created).Desc.Skip(pageIndex * pageSize).Take(pageSize).List();
    }

я пробовал оба

.TransformUsing(Transformers.DistinctRootEntity);

а также

.RootCriteria.SetResultTransformer(new DistinctEntityRootTransformer())

Он искажает как общее количество (он не возвращает результат без отличий), так и фактическое разбиение на страницы (пропустить / взять)

Как я могу это исправить?

Заранее спасибо, Андерс


person Anders    schedule 06.01.2011    source источник


Ответы (2)


Попробуйте что-нибудь вроде этого

public IPagedList<Client> Find(int pageIndex, int pageSize)
{
    Client clientAlias = null;

    var query = Session.QueryOver<Client>(() => clientAlias)

        .Select(
            Projections.Distinct(
                Projections.ProjectionList()
                    .Add(Projections.Property<Client>(x => x.Id).As("Id"))
                    .Add(Projections.Property<Client>(x => x.Name).As("Name"))
                    .Add(Projections.Property<Client>(x => x.Surname).As("Surname"))
                    .Add(Projections.Property<Client>(x => x.GivenName).As("GivenName"))
                    .Add(Projections.Property<Client>(x => x.EmailAddress).As("EmailAddress"))
                    .Add(Projections.Property<Client>(x => x.MobilePhone).As("MobilePhone"))
            )
        )
        .TransformUsing(Transformers.AliasToBean<Client>())

        .OrderBy(() => clientAlias.Surname).Asc
        .ThenBy(() => clientAlias.GivenName).Asc;

    var count = query
        .ToRowCountQuery()
        .FutureValue<int>();

    return query
        .Take(pageSize)
        .Skip(Pagination.FirstResult(pageIndex, pageSize))
        .List<Client>()
        .ToPagedList(pageIndex, pageSize, count.Value);
}
person Craig    schedule 24.02.2011
comment
Объяснение того, почему / как ваш ответ правильный, могло бы быть полезным, а не просто «Вот The Codez» - person Scott Weaver; 06.03.2013

У меня тоже была проблема с этим. Во-первых, Distinct работает, но только после вызова метода QueryOver.List.ToList(), поэтому query.skip не будет работать должным образом, просматривая дубликаты, создавая список, а затем уменьшая количество страниц из-за дубликатов. .

Самое простое, что я нашел, это ... просто сначала создайте список уникальных идентификаторов, а затем выполните разбивку на страницы по самим идентификаторам.

Затем в вашем наборе результатов вы можете просто выполнить идентификатор и получить идентификаторы только в вашем новом наборе результатов с разбивкой на страницы.

//Create your query as usual.. apply criteria.. do what ever you want.

//Get a unique set of ids from the result set.
var idList = query.
.Select(x => x.Id)
.List<long>().Distinct().ToList();

//Do your pagination here over those ids
List<long> pagedIds = idList.Skip(0).Take(10).ToList();

//Here what used to be non distinct resultset, now is..
List<T> resultquery.Where(() => 
item.Id.IsIn(pagedIds))
.List<Person>()
.ToList();

Особая благодарность.. https://julianjelfs.wordpress.com/2009/04/03/nhibernate-removing-duplicates-combined-with-paging/

person Jeffrey Holmes    schedule 31.05.2017