按版本分组

Group by version

The Setup

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”等的记录...当实体为 "deleted" 时,将添加另一条具有相同 ID、版本 + 1 且带有 [=45] 的记录=] IsDeleted 设置为 "true".

The Question

在我的存储库中,我想要一个 returns 可查询

的方法
  1. 按相同 ID 分组的实体
  2. 最高版本(=最新版本 实体的)
  3. IsDeleted = false

简而言之:我想检索一个实体列表,只有它们的最新记录(当实体未设置为 "IsDeleted" 时)

The Attempt

我尝试了两种不同的方法来解决这个问题。 correct/better 是哪一个? (或其他建议?)

选项 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 几乎可以按您希望的方式工作(基于评论)。您只需要从每个组中删除 .OrderByDescending(e => e.First().Version) 然后 select 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);
}

Try it online

查看您的要求:

  1. 按相同 ID 分组的实体
  2. 最高版本(=实体的最新版本)
  3. 未删除

如果在我看来你想要每个实体的最高未删除版本。

为了说得更清楚,我再说说文档的版本。您想要文档被删除之前的最后一个文档版本,或者如果尚未删除则为最后一个版本。

我的建议是先删除所有已删除的文档版本。然后将文档分组到具有相同 Id 的组中。

现在每个组都包含文档的所有未删除版本)。之后你拿最高版本号的文档。

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 overload that combines GroupBy and 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