我正在尝试构建自上次修订以来拉动日志的更改日志查询。
我现在需要根据某些规则合并日志。
这是我的ChangElog模型:
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>最后修订
由EntityID组成
不要带回实体具有更改的任何组。
如果有changeType.deleted但没有changeType。
仅带回最后一个changeType。
如果该组包含ChangeType.Created and ChangeType。
这就是我走了多远,但我不知道如何"带回小组的一部分":
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));
for 4.我如何将x变成一个新组,仅具有变频器的记录/值。如果组本身不包含changeType。创建但可能包含ChangeType。/div>
我做出的一些假设:
-
srcSet
是一组ChangeLogObject
项目。 - 根据列表中的要求5,为了启用"最后"项目的检索,您应该能够通过某个值对列表进行排序。为此,我引入了
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();
警告:
- LINQ语句未针对性能进行优化,因为这些语句并未包装在Iquerable中,以确保在数据库中评估这些查询。
这应该足以让您开始将需求的每个部分分解为查询。