改进Linq语句以消除对foreach循环的需要

时间:2012-09-20 15:15:51

标签: sql-server entity-framework c#-4.0 linq-to-sql

我有一个包含以下字段的MS SQL表。我正在使用实体框架:

EntryId
EntryType
Operation
UpdatedTime_UTC

EntryId和EntryType字段可以包含重复值。创建对象时,会添加一条记录,并将其“操作”字段设置为“已添加”。如果对象被修改,则使用与第一个记录相同的EntryId和EntryType值写入另一个记录,但“operation”字段将被设置为“modified”。当对象被删除时(你已经猜到了),另一条记录的前面记录与EntryId和EntryType值相同,但“operation”字段将被设置为“已删除”。

一些示例数据如下所示:

ID1, Type1, “added”,    2012-08-20 09:15:50
ID2, Type1, “added”,    2012-08-21 09:15:50
ID1, Type1, “modified”, 2012-08-22 09:15:50
ID1, Type1, “modified”, 2012-08-23 09:15:50
ID2, Type1, “deleted”,  2012-08-24 09:15:50

显示有关两个对象(ID1和ID2)的信息。两者都被添加到表中,但ID1被修改,ID2被删除。作为协调过程的一部分,我需要检查一个对象是否已被删除,我的表中必须有一条记录,其中匹配的EntryId的操作设置为“已删除”。如果没有我的代码将添加一个。

现在我的问题。当我的系统认为给定的“EntryType”没有对象时,我有一个函数被调用。我需要确认我的表中“EntryType”的所有记录都有一个“操作”设置为“已删除”的记录。在上面显示的数据中,“ID1”没有“已删除”条目。如果对象仍然存在则这很好但如果对象已经消失则很糟糕。我正在使用以下Linq获取一个分组列表,我在其中传递了我感兴趣的“entityType”。

        var item = _ctx.JournalSet
            .Where(x => x.EntryType == entityType)
            .OrderBy(x => x.UpdatedTime_UTC)
            .GroupBy(x => x.EntryId);

然后,我使用此代码查看每个组,看它是否有“已删除”条目。如果不是,我在表格中添加新记录。

        foreach (var item in result)
        {
            if (item.Last().Operation != "deleted")
            {
                // no 'deleted' entry found. time to add a new entry.
            }
        }

我想要做的是修改我的Linq语句,以便只在需要添加删除的条目时才返回EntryId和EntryType详细信息。

附加信息:删除的记录的日期时间总是晚于“添加”或“修改”记录,因此在按“UpdatedTime_UTC”排序时,最后一个条目应为“已删除”,如果它存在于给定的entryId

是否有可能创建一个Linq语句来完成上述操作而不需要foreach的东西?

2 个答案:

答案 0 :(得分:2)

你尝试过这样的事吗?

    var item = _ctx.JournalSet
         .Where(x => x.EntryType == entityType)
         .OrderBy(x => x.UpdatedTime_UTC)
         .GroupBy(x => x.EntryId)
         .Where(y => y.Last().Operation != "deleted"); 

答案 1 :(得分:0)

我会找到您缺少已删除条目的记录,然后根据需要添加它们:

 var itemsToAdd = _ctx.JournalSet
        .Where(x => x.EntryType == entityType)
        .OrderBy(x => x.UpdatedTime_UTC)
        .GroupBy(x => x.EntryId)
        .Where(grp => grp.Last().Operation != "deleted");

然后您可以使用foreach添加项目,甚至可以通过第二个LINQ Select语句(映射到新类型)执行此操作,具体取决于您要添加的集合。第二个陈述可能类似于:

 collection.AddRange(itemsToAdd.Select(grp => new YourType(grp.Key.EntryId, "deleted")));

(这是假设一个构造函数,它采用ID +“删除”,根据需要进行编辑......)