我正在尝试构建一个自上次修订以来提取日志的更改日志查询。
我现在需要根据一些规则整合日志。
这是我的更新日志模型:
public abstract class ChangeLogObject : TrackedObject {
/// <summary>
/// Type of transaction that occured
/// </summary>
public ChangeType ChangeType { get; set; }
/// <summary>
/// Original Id of the stateful object this changelog was created against
/// </summary>
public long EntityId { get; set; }
}
public enum ChangeType {
Created,
Updated,
Deleted
}
所以我需要遵循的步骤是:
获取ID&gt;最新修订
Group By EntityId
不要带回实体具有ChangeType.Created和ChangeType.Deleted的任何组
如果存在ChangeType.Deleted但没有ChangeType.Created(从组中删除更新的记录),请不要带回ChangeType.Updated记录
如果有倍数,则仅返回最后一条ChangeType.Updated记录
如果该组包含ChangeType.Created和ChangeType.Updated,则只返回最后一个ChangeType.Updated,但将其更改为ChangeType.Created
这是我已经走了多远,但我不知道如何'带回一部分人':
var newChanges =
// 1. Get where greater than last revision
srcSet.Where(x => x.Id > lastRevision)
// 2. Group by EntityId
.GroupBy(x => x.EntityId)
// 3. Don't bring back created and deleted (it's come and gone)
.Where(x => !(x.Any(y => y.ChangeType == ChangeType.Created) &&
x.Any(y => y.ChangeType == ChangeType.Deleted)))
// 4. Only bring back Deleted if no created (don't edit something you're about to delete)
.Where(x => (!x.Any(y => y.ChangeType == ChangeType.Created) &&
x.Any(y => y.ChangeType == ChangeType.Deleted)))
//create new grouping, but only use the delete record????
//convert back to individual change logs
.Select(x => x.ToList()
//maybe order by ID?
.OrderBy(y => y.Id));
对于4.如何将x转换为仅包含ChangeType.Deleted的记录/值的新组,如果组本身不包含ChangeType.Created但可能包含ChangeType.Updated?
答案 0 :(得分:1)
我做过的一些假设:
srcSet
是一组ChangeLogObject
项。ChangeDate
字段,该字段是更改发生的日期。 在我的示例中,TrackedObject
如下所示:
public abstract class TrackedObject
{
public int Id { get; set; }
public DateTime ChangeDate { get; set; }
}
我已经分解了查询的每一步,并根据要求对其进行了编号:
var lastRevision = 2;
var srcSet = new List<ChangeLogObject>();
// 1. & 2.
var entityGroupsByEntityId = srcSet
.Where(m => m.Id > lastRevision) // greater than last revision
//.OrderByDescending(m => m.ChangeDate)
.GroupBy(m => m.EntityId)
.Select(group => new
{
EntityId = group.Key,
ChangeCount = group.Count(),
Changes = group.ToList().OrderByDescending(m => m.ChangeDate)
});
// 3.
var entityGroupsWithNoDeleteAndCreate = entityGroupsByEntityId
.Where(group => !(group.Changes.Any(m => m.ChangeType == ChangeType.Created)
&& group.Changes.Any(m => m.ChangeType == ChangeType.Deleted))); // it doesn't contain both creates and deletes
// 4.
var entityGroupsWithoutDeletedAndNoCreate = entityGroupsWithNoDeleteAndCreate
.Where(group => !(group.Changes.Any(m => m.ChangeType == ChangeType.Deleted)
&& (group.Changes.Count(m => m.ChangeType == ChangeType.Created) < 1))); // it doesn't contain a delete without a create
// 5.
var entityGroupsWithUpdatedButNoCreated = entityGroupsWithoutDeletedAndNoCreate
.Where(group => group.Changes.Any(m => m.ChangeType == ChangeType.Updated)
&& !group.Changes.Any(m => m.ChangeType == ChangeType.Created)) // it updated but not created
.Select(group => new ChangeLogObject
{
EntityId = group.EntityId,
ChangeDate = group.Changes.First().ChangeDate,
ChangeType = group.Changes.First().ChangeType // don't change the type
});
// 6.
var entityGroupsWithCreatedAndUpdatedOnly = entityGroupsWithoutDeletedAndNoCreate
.Where(group => group.Changes.Any(m => m.ChangeType == ChangeType.Created)
&& group.Changes.Any(m => m.ChangeType == ChangeType.Updated)) // it contains both created and updated
.Select(group => new ChangeLogObject
{
EntityId = group.EntityId,
ChangeDate = group.Changes.First(m => m.ChangeType == ChangeType.Updated).ChangeDate, // bring back the first updated record
ChangeType = ChangeType.Created // change the type to created
});
// Join the 2 sets of Updated and Created changes
var finalResult = entityGroupsWithUpdatedButNoCreated.Union(entityGroupsWithCreatedAndUpdatedOnly).ToList();
警告:
这应该足以让您开始将需求的每个部分分解为查询。