EF Core - 跨 4 个表的多对多关系

EF Core - Many-To-Many Relationship across 4 Tables

考虑以下 3 个实体 ABCA-to-C 是多对多关系。 B-to-A是一对多的关系(B有很多A,这意味着B-to-C也是多对多)。

如果您觉得这些过于复杂的关系过于模糊,请考虑以下示例:

所以(暗示):

问题:如何建立这种关系的实体?使用以下代码,我已经建立了Album-to-Artist之间的关系,Track-到-Artist如何创建 Artist-Album 关系 因为它似乎需要加入 4 tables/entities.

public class Context: DbContext
{

    // irrelevant code omitted...        

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TracksToArtists>()
            .HasKey(r => new {r.TrackId, r.ArtistId});

        modelBuilder.Entity<TracksToArtists>()
            .HasOne(r => r.Track)
            .WithMany(t => t.Artists)
            .HasForeignKey(r => r.TrackId);

        modelBuilder.Entity<TracksToArtists>()
            .HasOne(r => r.Artist)
            .WithMany(a => a.Tracks)
            .HasForeignKey(r => r.ArtistId);
    }
}

public class Track
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public Guid AlbumId { get; set; }
    public Album Album { get; set; }

    public List<TracksToArtists> Artists { get; set; }
}

public class Album
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public List<Track> Tracks { get; set; }

    // TODO: create album-to-artist many-to-many relationship
    // public List<SomethingArtistMaybe?> Artists { get; set; }
}
public class Artist
{
    public Guid Id { get; set; }
    public string Name { get; set; }

    public List<TracksToArtists> Tracks { get; set; }

    // TODO: create album-to-artist many-to-many relationship
    // public List<SomethingAlbumMaybe?> Albums { get; set; }
}
 // many-to-many relationship
public class TracksToArtists
{
    public Guid TrackId { get; set; }
    public Track Track { get; set; }

    public Guid ArtistId { get; set; }
    public Artist Artist { get; set; }
}

如果只使用原始 SQL 查询,这是非常简单的,但是使用 ORM 一切都会变得有点痛苦。

Optimly,我想避免引入 AlbumToArtist table,因为它可能会造成数据不一致。它应该是这样的:

如果我没理解错的话,ArtistAlbum 没有直接关系,关系仅通过 Track.

考虑把Album放在中间,这样每个Artist有多个Album,反之亦然(多对多),然后有Album导航到许多 Track(一对多)。

无论如何,无论您是选择按照您的问题还是按照我的建议保留您的模型,从一个点到另一个点访问图形(在您的问题 Album 中每个 Artist),使用eager loading:

public async Task<IEnumerable<Album>> GetAlbums(Artist artist)
{
    return await myDbContext.Artists
                   .Include(artist => artist.Tracks)
                   .ThenInclude(track => track.Album)
                 .Where(a.Id == artist.Id)
                 .Select(artist => 
                   artist.Tracks.Select(track =>
                     track.Album))
                 .Distinct()
                 .ToListAsync();
}

您还可以启用 lazy-loading,这样您就不必在查询中明确包含导航属性,但这样做会产生性能成本。