按版本分组

时间:2018-11-08 06:18:50

标签: c# linq repository

  

设置

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. 按相同ID分组的实体
  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 :(得分:1)

我认为您的选项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);
}

Try it online

答案 1 :(得分:1)

查看您的要求:

  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