关于c#:在LinQ Lambda Join中检索索引

Retrieve index in LinQ Lambda Join

我对所有的.NET东西都很陌生,只是想知道我想做什么。我使用Linq lambda查询返回带有Select语句的列表值已有一段时间了,如下所示:

1
2
3
4
5
6
7
8
        var data = list.Select((x, i) =>
            new
            {
                Index = i,       // <--- this is what I need!
                Value = x.Value,
                Text = x.Text
            })
            .ToList();

问题是我有一个linq lambda连接表达式,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
        var data = DataBase.Table1
            .Join(DataBase.Table2,
                x => x.Id,
                y => y.Id,
                (x, y) => new    // <--- I can't do the same here :(
                {
                    Index = ???, // <--- Here is where I need the index!!
                    Value = x.Id,
                    Text = y.Description,
                })
            .OrderBy(x => x.Id)
            .ToList();

我的问题是,如何在第二个LINQ查询中检索索引,就像在第一个查询中一样?


不能将Select(Func)与linq to sql一起使用。如果尝试执行第一个查询,将看到NotSupportedException:

Unsupported overload used for query operator 'Select'

可以将此运算符与Linq to对象一起使用。只需使用AsEnumerable()调用将查询执行移到内存即可。使用第二个查询,在收到join结果并将执行移动到内存后添加另一个投影:

1
2
3
4
5
6
7
8
9
10
 var data = DataBase.Table1
            .Join(DataBase.Table2,
                t1 => t1.Id,
                t2 => t2.Id,
                (t1, t2) => new { Value = t1.Id, Text = t2.Description }
            )
            .AsEnumerable() //otherwise next operator cannot be translated to SQL
            .Select((x,i) => new { x.Value, x.Text, Index = i})
            .OrderBy(x => x.Value)
            .ToList();

更新:如果需要t2的索引,可以用GroupJoin代替Join

1
2
3
4
5
6
7
8
9
10
11
 var data = DataBase.Table1
            .GroupJoin(DataBase.Table2,
                t1 => t1.Id,
                t2 => t2.Id,
                (t1, t2items) => new { Value = t1.Id, t2items }
            )
            .AsEnumerable() //otherwise next operator cannot be translated to SQL
            .SelectMany(x => x.t2items.Select((t2, i) =>
               new { x.Value, Text = t2.Description, Index = i}))
            .OrderBy(x => x.Value)
            .ToList();

如果您需要两个索引,那么将整个连接移动到内存:

1
2
3
4
5
6
7
8
9
10
11
12
 var data = DataBase.Table1.AsEnumerable().Select((t1,i) => new { t1, i })
            .Join(DataBase.Table2.AsEnumerable().Select((t2,i) => new { t2, i }),
                  x1 => x1.t1.Id,
                  x2 => x2.t2.Id,
                  (x1, x2) => new {
                      Value = x1.t1.Id,
                      Text = x2.t2.Description,
                      Index1 = x1.i,
                      Index2 = x2.i
                  })
            .OrderBy(x => x.Value)
            .ToList();