设置
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设置为“真”。
问题
在我的存储库中,我想要一个方法,该方法返回可查询的
因此,简而言之:我想检索实体列表,仅包含其最新记录(当实体未设置为“ 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);
}
答案 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);
}
答案 1 :(得分:1)
查看您的要求:
在我看来,您希望每个实体都提供最高的未删除版本。
为使内容更清楚,我将讨论文档的版本。您想要删除文档之前的最后一个文档版本,如果尚未删除,则需要最后一个文档版本。
我的建议是首先删除所有删除的文档版本。然后将文档按具有相同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