linq .groupby .Where.选择新分组项目



我正在尝试构建自上次修订以来拉动日志的更改日志查询。

我现在需要根据某些规则合并日志。

这是我的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
}

所以我需要遵循的步骤是:

  1. 获取id>最后修订

  2. 由EntityID组成

  3. 不要带回实体具有更改的任何组。

  4. 如果有changeType.deleted但没有changeType。

  5. 仅带回最后一个changeType。

  6. 如果该组包含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>

我做出的一些假设:

  1. srcSet是一组ChangeLogObject项目。
  2. 根据列表中的要求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();

警告:

  1. LINQ语句未针对性能进行优化,因为这些语句并未包装在Iquerable中,以确保在数据库中评估这些查询。

这应该足以让您开始将需求的每个部分分解为查询。

最新更新