linq延迟符合条件的元素

时间:2013-10-16 09:42:24

标签: c# linq

我有一个看起来像这样的表:

 ActionID | ActionTime | ActionType | UserID
    1       3/22/2013        4          8
    2       3/31/2013        1          8
    3       4/12/2013        3          8

每个Action都有几个ActionTime,我希望得到最新 ActionTime属于某些ActionType的用户的所有ActionID。

这是我的查询,但在我测试时,它没有按预期工作:

var TheActionType = list of bytes (ie. [1, 3, 5])

(from a in MyDC.Actions
 where a.UserID == TheUserID
 where TheActionType.Contains(a.ActionType)
 orderby a.ActionTime descending (//I only want the last ActionTime each user)
 select a.ActionID).ToList();

因此,如果我在ActionType中传入[4,1],我不应该得到任何回复,因为最后一个ActionTime的ActionType为3。

基本上,我知道我可以通过首先使用orderby.FirstOrDefault()获取最新的ActionID,然后使用字节列表运行第二个.Contains()查询来重做此操作,但我想知道如果只用一个查询就可以做到这一点。

感谢。

1 个答案:

答案 0 :(得分:1)

你会做这样的事情:

MyDC.Actions
    .GroupBy(x => x.UserID)
    .Select(g => g.OrderByDescending(x => x.ActionTime)
                  .First())
    .Where(x => TheActionType.Contains(x.ActionType))
    .Select(x => x.ActionID);

执行以下操作:

  1. UserID
  2. 对操作进行分组
  3. 对于每个用户,选择具有最高ActionTime的操作,换句话说:它选择最年轻的操作。
  4. 结果按允许的操作类型列表进行过滤。
  5. 从剩余的操作中选择ActionID
  6. 示例:http://ideone.com/KbwPBI

    我按用户ID删除了过滤器,因为您说

      

    我只想要每个用户的最后一个ActionTime

    因此,如果每个用户匹配指定的操作类型,则此查询将返回最后一个操作ID。

    如果您真的只想要单个用户的最新操作,只需在上一个查询中添加Where

    MyDC.Actions
        .Where(x => x.UserID == TheUserID)
        .GroupBy(x => x.UserID)
        .Select(g => g.OrderByDescending(x => x.ActionTime)
                      .First())
        .Where(x => TheActionType.Contains(x.ActionType))
        .Select(x => x.ActionID)
        .SingleOrDefault();