如何在Linq到EF5中查询多对多的关系

时间:2013-06-29 14:08:48

标签: asp.net vb.net entity-framework many-to-many entity-framework-5

我正在学习EF5并建立一个小网站,只显示一些歌曲和歌手。由于歌曲可以由不止一位歌手演唱而且歌手会有很多歌曲,所以我的EF模型如下所示。

enter image description here

我想在表格中显示所有歌曲及其相关歌手的列表,所以我写了一个查询,这是迄今为止的。

Dim res = context.Songs _
        .SelectMany(Function(song) song.Artists, Function(s, a) New With
                                                                {.SongTitle = s.SongTitle, _
                                                                .ArtistName = a.ArtistName, _
                                                                 .Lyrics = s.Lyrics})

但我得到的结果如下。

enter image description here

您将看到Lucky在表格中显示两次。我不希望这种情况发生。我只想显示一次,但在Artist列中加入了两个歌手。我试图阅读教程和许多论坛帖子,但这些教程并没有让这复杂。

那么如何更改查询以返回这样的内容呢?

enter image description here

1 个答案:

答案 0 :(得分:1)

我必须用C#写答案,希望你能把它翻译成VB。

我会做两处修改:

  • 首先,在这种情况下,只需使用Select代替SelectMany
  • 其次,引入一个名为ViewModel而不是匿名类型,因为它允许您添加一个方法或自定义只读属性,以后会有所帮助。

ViewModel看起来像这样:

public class SongViewModel
{
    public string SongTitle { get; set; }
    public string Lyrics { get; set; }
    public IEnumerable<string> ArtistNames { get; set; }

    public string ArtistNamesString
    {
        get { return string.Join(", ", ArtistNames); }
    }
}

然后您可以使用此查询:

var res = context.Songs.Select(s => new SongViewModel
{
    SongTitle = s.SongTitle,
    Lyrics = s.Lyrics,
    ArtistNames = s.Artists.Select(a => a.ArtistName)
});

现在,要列出结果,您可以使用这样的循环(带控制台输出的示例):

foreach (var item in res)
{
     Console.WriteLine(string.Format("{0} {1} {2}",
         item.SongTitle, item.Lyrics, item.ArtistNamesString);
}

仅列出每首歌曲一次,艺术家名称显示为逗号分隔列表。