Проблема с nHibernate Distinct и пейджингом - PullRequest
7 голосов
/ 06 января 2011

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

    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())

Он сбивает обаобщее количество (возвращает результат без различий) и фактическое подкачка (Пропустить / Взять)

Как это исправить?

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

Ответы [ 2 ]

2 голосов
/ 31 мая 2017

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

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

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

//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/

2 голосов
/ 24 февраля 2011

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

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...