麻烦的“简单”linq查询

时间:2014-02-20 23:52:57

标签: c# linq entity-framework linq-to-sql

我有两个表中的数据 - Albums表和Tracks表。两者之间存在一对多的关系,数据库结构反映了我的下面的类。我正在尝试获取一张专辑,并且根据艺术家名称关联曲目(我知道数据未正确规范化 - 应该有一个Artist实体,但我的源数据不支持!)

public class Album
{
    public string ArtistName { get; set;}  
    public string AlbumId { get; set; }
    public string AlbumName { get; set; }
    public int TrackCount { get; set; }
    public string Year { get; set; }
    public string Genre { get; set; }
    public string CoverArt { get; set; }
    public string Biography { get; set; }

    // Navigation properties
    public ICollection<Track> Tracks { get; set; }
}
public class Track
{
    public string TrackId { get; set; }
    public int TrackNumber { get; set; }
    public string TrackName { get; set; }
    public string AlbumId { get; set; }
}

我获取匹配相册列表的查询工作正常:

var albums = DataContext.Albums.Where(a => a.ArtistName == artistName  && a.AlbumName == album).ToList();

但以下声明不起作用:

var tracks = DataContext.Tracks.Where(a => a.AlbumId == albums.Select(al => al.AlbumId).SingleOrDefault());

运行后,tracks变量包含:

{System.Data.Entity.Infrastructure.DbQuery<MusicApp.Model.Track>}   System.Linq.IQueryable<MusicApp.Model.Track> {System.Data.Entity.Infrastructure.DbQuery<MusicApp.Model.Track>}

我尝试将.ToList()附加到我的Linq语句中并且只返回错误:

Additional information: Unable to create a constant value of type 'MusicApp.Model.Album'. Only primitive types or enumeration types are supported in this context.

我确信解决方案非常简单,但我是Linq的新手并且无法想象这一点。任何帮助将不胜感激!

5 个答案:

答案 0 :(得分:1)

您可以包含所需的导航属性:

var albumsWithTheirTracks = DataContext.Albums
                .Where(a => a.ArtistName == artistName)
                .Include("Tracks")
                .ToList();

执行此操作将使用相关实体填充每个专辑的曲目集合。

您的另一个选择是在您的相册模型中将您的曲目导航属性标记为虚拟:

public virtual ICollection<Track> ...

将导航属性标记为虚拟可启用延迟加载,并将带有相关实体的原始查询专辑。如果您不选择延迟加载,则可以使用Include方法指定要与您要求的原始相册一起使用的导航属性。

答案 1 :(得分:1)

var albums = DataContext.Albums.Where(a => a.ArtistName == artistName  && a.AlbumName == album).ToList();
List<string> albumIds = albums.Select(s => s.AlbumId).Distinct().ToList();

var tracks = DataContext.Tracks.Where(w => albumIds.Contains(w.AlbumId)).ToList();

答案 2 :(得分:0)

如果您已有专辑的数据,为什么不尝试:

var tracks = from t in DataContext.Tracks
             joins a in albums on a.AlbumId equals t.AlbumId
             select t;

答案 3 :(得分:0)

试试这个:

var query = from t in DataContext.Tracks
            join a in DataContext.Albums on t.AlbumId equals a.AlbumId
            where a.ArtistName == "artistName" && a.AlbumName == "album"
            select t;

答案 4 :(得分:0)

其他人正在制造的不必要的加入,是我个人的抱怨,因为他们难以遵守代码。

var query = from t in DataContext.Tracks
            where t.Artists.Any(a => a.ArtistName == "artistName" 
                         && a.AlbumName == "album")
            select t;