Linq GroupBy抛出ArgumentOutOfRangeException

时间:2015-06-22 12:45:04

标签: c# linq

我有这两个表

Animals           Activities
+----+-------+    +----+------------+----------+------------+
| Id | Name  |    | Id | Activity   | FkAnimal | Date       |
+----+-------+    +----+------------+----------+------------+
| 1  | Cats  |    | 1  | Ball       | 2        | 2015-05-21 |
+----+-------+    +----+------------+----------+------------+
| 2  | Dogs  |    | 2  | Pet        | 2        | 2015-06-07 |
+----+-------+    +----+------------+----------+------------+
| 3  | Birds |    | 3  | Running    | 1        | 2014-11-03 |
+----+-------+    +----+------------+----------+------------+
                  | 4  | Kill a fly | 1        | 2014-08-05 |
                  +----+------------+----------+------------+
                  | 5  | Kill a fly | 3        | 2014-08-05 |
                  +----+------------+----------+------------+

我想要的是此查询的结果

SELECT Animals.Name, Animals.Id, Activities.Data
FROM Activities
INNER JOIN Animals ON Animals.Id = Activities.Id
GROUP BY Animals.Name, Animals.Data

来自实体框架的LINQ

这是我的尝试:

//My repository is of type IRepository<Activities>
var list = Repository.GetAll().GroupBy(a => a.Animals).Select((grouping,i) => new {
    name = grouping.Key.Name,
    id = grouping.Key.Id,
    data = grouping.ElementAt(i).Data
}).ToList();

不幸的是,ToList()方法会生成ArgumentOutOfRangeException,如果我调试lambda,则会显示i超出范围

2 个答案:

答案 0 :(得分:1)

i中的.Select((grouping,i) =>是该组的索引。在您的示例中,.GroupBy(a => a.Animals)将返回IGrouping,这实际上只是一个IEnumerable属性Key.GroupBy(a => a.Animals)的结果松散地看起来像这样(不确定你的DbContext是什么样的):

{[
    {
        Key: Dogs
        GetEnumerator(): [
            {
                Id: 1
                Activity: Ball
                Date: 2015-05-21
            },
            {
                Id: 2
                Activity: Pet
                Date: 2015-06-07
            }
        ]
    },
    {
        Key: Cats
        GetEnumerator(): [
            {
                Id: 3
                Activity: Running
                Date: 2014-11-03
            },
            {
                Id: 4
                Activity: Kill a fly
                Date: 2014-08-05
            }
        ]
    },
    {
        Key: Birds
        GetEnumerator(): [
            {
                Id: 5
                Activity: Kill a fly
                Date: 2014-08-05
            }
        ]
    }
]}

Select方法迭代组,而不是组中的元素。因此,在这种情况下,i中的.Select((grouping,i) =>是指组中的索引(有三组)不是组中的元素。在您的选择中,您正在调用data = grouping.ElementAt(i).Datagrouping在这种情况下是IGropuing,这是IEnumerable,因此ElementAt(i)要求任何一个组中的第i个元素目前正在评估中。当你得到第三组时,i将为2,但组中只有一个元素,因此例外;至少在这个例子中,你的小组可能会以不同的顺序返回,但原则是相同的。

你可能想要这样的东西:

var list = 
    Repository
    .GetAll()
    .GroupBy(a => a.Animals)
    .Select(grouping => new {
        name = grouping.Key.Name,
        id = grouping.Key.Id,
        data = grouping.Select(x => x)
    }).ToList();

答案 1 :(得分:0)

这是否有效......

var res= from act in Repository.GetAll()
       let anm=act.Animals.Single(a=>a.Id=act.FkAnimal)
       select new {
          anm.Id, anm.Name, act.Activity
       };