【问题标题】:How to use LINQ to select into an object?如何使用 LINQ 选择对象?
【发布时间】:2012-07-19 05:23:35
【问题描述】:

我的数据看起来像这样:

UserId   |  SongId
--------   --------
1          1
1          4
1          12
2          95

我也有以下课程:

class SongsForUser
{
    public int User;
    public List<int> Songs;
}

我想做的是使用 LINQ 从我的数据中进行选择,以创建 SongsForUser 对象的集合。以下是我目前想出的:

var userCombos = songs.UserSongs.Select(x => new SongsForUser() { User = x.UserId, 
                                                                  Songs = /*What goes here?*/ });

我将如何填充我的Songs 列表?

所以结果应该是两个 SongsForUser 对象。对于用户1Songs 列表中有 3 个项目。对于用户 2,它将在 Songs 列表中有 1 项。

【问题讨论】:

    标签: c# .net linq linq-to-entities


    【解决方案1】:
    songs.UserSongs.GroupBy(x => x.User).Select(g => new SongsForUser() 
    { 
        User = g.Key,
        Songs = g.Select(s => s.SongId).ToList()
    });
    

    【讨论】:

    • 为什么只在投影中选择歌曲 ID,而不是作为分组的一部分?
    • 这会在ToList 部分引发错误。我相信这可能是因为这是 Linq to Entities。错误:LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[System.String] ToList[String](System.Collections.Generic.IEnumerable1[System.String])' method, and this method cannot be translated into a store expression.
    • @AbeMiessler 确保您有using System.Linq
    • 不错。想出了一个类似的解决方案。 +1
    • @AbeMiessler:如果您在开头提到 LINQ to Entities,那就太好了……
    【解决方案2】:

    我怀疑你想要:

    var songsByUser = songs.UserSongs
                           .GroupBy(song => song.UserId, song => song.SongId)
                           .Select(g => new SongsForUser { User = g.Key,
                                                           Songs = g.ToList() });
    

    解释一下,GroupBy 之后会有一堆组,其中每个组的键是用户 ID,组内的值是歌曲 ID:

    Key = 1, Values = 1, 4, 12
    Key = 2, Value = 95
    

    然后您只需将其转换为您的 SongsForUser 类型。请注意,在对象初始化程序中调用构造函数时,您不需要显式包含 () - 它是隐式的,除非您需要指定构造函数参数。

    顺便说一句,您可以在一个 GroupBy 电话中完成所有这些操作:

    var songsByUser = songs.UserSongs
             .GroupBy(song => song.UserId, song => song.SongId,
                      (user, ids) => new SongsForUser { User = user,
                                                        Songs = ids.ToList() });
    

    就我个人而言,我通常会发现单独的Select 调用更具可读性。

    您也可以使用查询表达式来完成所有这些操作:

    var songsByUser = from song in songs.UserSongs
                      group song.SongId by song.UserId into g
                      select new SongsForUser { User = g.Key, Songs = g.ToList() };
    

    编辑:以上是“提供者中立的”,但听起来它不适用于 LINQ to Entities。你也许可以让它像这样工作:

    var songsByUser = songs.UserSongs
                           .GroupBy(song => song.UserId, song => song.SongId)
                           .AsEnumerable()
                           .Select(g => new SongsForUser { User = g.Key,
                                                           Songs = g.ToList() });
    

    AsEnumerable 调用将强制在数据库中完成分组,但最终投影(包括ToList 调用)在本地完成。不过,您应该检查生成的 SQL 的效率。

    【讨论】:

      【解决方案3】:

      假设您有以下内容:

      public class SongsForUser
      {
          public int UserId;
          public List<int> Songs;
      }
      

      然后像这里这样的功能就可以了。清单就在那里 一些数据进行测试。

          public void Group()
          {
              List<Tuple<int, int>> SongRelations = new List<Tuple<int, int>>();
      
              SongRelations.Add(new Tuple<int, int>(1, 1));
              SongRelations.Add(new Tuple<int, int>(1, 4));
              SongRelations.Add(new Tuple<int, int>(1, 12));
              SongRelations.Add(new Tuple<int, int>(2, 95));
      
              var list = SongRelations.GroupBy(s => s.Item1)
                                      .Select(r => new SongsForUser()
                                      {
                                          UserId = r.Key,
                                          Songs = r.Select(t => t.Item2).ToList(),
                                      });
          }
      

      list 之后包含 2 个 SongsForUser 类型的项目。 一个包含用户 1 和包含 1、4 和 12 的歌曲列表 和一个用户 2 和一个包含 95 的歌曲列表。

      【讨论】:

        【解决方案4】:

        以最简单的形式,您可以:

        List<MapPoint> points = db.PropertyResearches.Where(a => a.deptId == 66).Select(x => new MapPoint { property = x.notes.Substring(0, 10), latitude = x.lat, longitude = x.@long }).ToList();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-26
          • 1970-01-01
          • 1970-01-01
          • 2019-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多