Группировать по версии - PullRequest
0 голосов
/ 08 ноября 2018

Настройка

public abstract class Entity
{
    public Guid Id { get; set; }//Primary key
    public int Version { get; set; }//Primary key
    public DateTime Created { get; set; }
    public User CreatedBy { get; set; }
    public bool IsDeleted { get; set; }
}

И Id, и Version являются первичным ключом. Сущность автоматически генерирует Id при создании и имеет версию по умолчанию «0». Когда сущности обновляются, добавляется другая запись с тем же Id и версией «1» и т. Д. Когда сущность «удаляется», добавляется другая запись с тем же Id, версией + 1 и свойством IsDeleted, установленным в « правда».

Вопрос

В моем репозитории я хочу иметь метод, который возвращает запрашиваемое значение

  1. Объекты, сгруппированные по одному идентификатору
  2. Самая высокая версия (= последняя версия субъекта)
  3. IsDeleted = false

Итак, вкратце: я хочу получить список сущностей, только с их последней записью (когда для сущности не установлено значение "IsDeleted")

Попытка

Я пробовал 2 разных способа решить эту проблему. Какой из них правильный / лучше здесь? (или другие предложения?)

Вариант 1:

public IQueryable<TEntity> Get<TEntity>(int page, int size) where TEntity : Entity
{
    return _context
        .Query<TEntity>()
        .OrderByDescending(x => x.Version)
        .GroupBy(x => x.Id)
        .SelectMany(x => x)
        .Where(x => !x.IsDeleted)
        .Skip(page * size)
        .Take(size);
 }

Вариант 2:

public IQueryable<TEntity> Get<TEntity>(int page, int size) where TEntity : Entity
{
    return _context
        .Query<TEntity>()
        .GroupBy(d => d.Id)
        .Select(g => g.OrderByDescending(d => d.Version))
        .OrderByDescending(e => e.First().Version)
        .SelectMany(e => e)
        .Where(x => !x.IsDeleted)
        .Skip(page * size)
        .Take(size);
}

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Рассматривая ваши требования:

  1. Объекты, сгруппированные по одному и тому же идентификатору
  2. Высшая версия (= последняя версия сущности)
  3. not IsDeleted

Если мне кажется, что вы хотите самую высокую не удаленную версию из каждой сущности.

Чтобы было понятнее, я расскажу о версиях документа. Требуется последняя версия документа перед удалением документа или последняя, ​​если она еще не была удалена.

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

Теперь каждая группа содержит все не удаленные версии документа). После этого вы берете документ с наибольшим номером версии.

var result = entities                     // from the collection of document
    .Where(entity => !entity.IsDeleted)   // keep the non-deleted ones
    .GroupBy(entity => entity.Id)         // group them into groups with same Id

    // now every group contains all non-deleted versions of a document
    // select the newest document,                         // to do this
    .Select(group => group                                 // order all items in a group by
        .OrderByDescending(groupItem => groupItem.Version) // descending Version number
        .FirstOrDefault());                                // and select the first one

Существует перегрузка GroupBy, которая объединяет GroupBy и Select :

 // group the remaining non-deleted items into groups with same Id
.GroupBy(entity => entity.Id     
   (id, entitiesWithThisId => entitiesWithThisId.OrderByDescending(entity => entity.Version)
                             // order all entities of a group by descending Version number
        .FirstOrDefault());  // and select the first one
0 голосов
/ 08 ноября 2018

Я думаю, что ваш вариант 2 почти работает так, как вы хотите (основываясь на комментариях). Вам просто нужно удалить свой .OrderByDescending(e => e.First().Version) и затем выбрать e.First() из каждой группы:

public IQueryable<TEntity> Get<TEntity>(int page, int size) where TEntity : Entity
{
    return _context
        .Query<TEntity>()
        .GroupBy(d => d.Id)
        .Select(g => g.OrderByDescending(d => d.Version))
        .Select(e => e.First())
        .Where(x => !x.IsDeleted)
        .Skip(page * size)
        .Take(size);
}

Попробуйте онлайн

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...