EF Core:同一实体之间的多个多对多关系

EF Core: multiple many-to-many relationships between the same entities

我正在做一个需要多对多关系的项目。我知道为了做到这一点,您应该创建 join tables。

在我的项目中,我们有用户、系列和剧集。为简单起见,我们将在这里忽略剧集。用户有最喜欢的系列和观看列表。

public class User 
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string FullName { get; set; }

    public List<UserSeries> WatchList { get; }
    public List<UserSeries> FavoriteSeries { get; }
}

加入实体:

public class UserSeries
{
    public int UserId { get; set; }
    public User User { get; set; }

    public int SeriesId { get; set; }
    public Series Series { get; set; }
}

Series 实体不是那么重要,它是标准类型的实体。

现在我正在尝试为 EF Core 进行配置,我使用 Fluent API 配置 (IEntityTypeConfiguration) 来执行此操作。我首先尝试像这样制作 UserSeriesConfiguration

class UserSeriesConfiguration : IEntityTypeConfiguration<UserSeries>
{
    public void Configure(EntityTypeBuilder<UserSeries> builder)
    {
        builder.ToTable("UserSeries");
        builder.HasKey(us => new { us.UserId, us.SeriesId });

        builder.HasOne(us => us.User).WithMany(u => u.FavoriteSeries).HasForeignKey(ue => ue.UserId);
        builder.HasOne(us => us.User).WithMany(u => u.WatchList).HasForeignKey(us => us.UserId);
        builder.HasOne(us => us.Series).WithMany().HasForeignKey(us => us.SeriesId);
    }
}

EF Core 抱怨:

Cannot create a relationship between 'User.WatchList' and 'UserSeries.User', because there already is a relationship between 'User.FavoriteSeries' and 'UserSeries.User'. Navigation properties can only participate in a single relationship.

我尝试制作一个 UserFavoriteSeriesConfiguration 和一个 UserWatchListConfiguration,并给它们单独的 table 名称,但这相当丑陋,导致重复代码和大量额外配置 类(特别是因为有剧集等。我也有这个设置),最糟糕的是:它仍然没有用...

这个问题有简单的解决方法吗?最坏的情况我将不得不创建连接实体(而不是 UserSeries 然后可以创建 UserFavoriteSeries),但这加倍了我在前面段落中描述的负面影响:很多额外的 类 和重复代码。

A "faved" 系列与 "watchlisted" 系列是不同的关系,因此在将数据存储在数据库中时,您需要以某种方式能够区分这两种不同类型的关系.

现在,您只有一个 table 来映射两个关系,这就是正在发生的事情:

你看到问题了吗? UserSerie table 中有重复的行,可能是因为 Diego 标记为 Fav 系列 Bojack 并且他也将其添加到他的 [=16] =].但是,无法分辨哪一行代表 Fav 关系,哪一行代表 Watchlisted 关系。

第一种方法:将附加属性添加到 UserSerie 作为鉴别器

一种方法是添加一个新属性(数据库 table 列)来存储 UserSerie 之间的关系类型。

您现在可以清楚地看到每行代表什么类型的关系:F 是最喜欢的系列,W 是观看列表系列。

添加其他类型的关系(推荐的系列、不喜欢的系列或其他)会非常容易。

这意味着现在 User 实体将只有一个 UserSerie 列表,其中每个 UserSerie 都有一个 Type 属性 可以检查以确定该用户与该系列之间的关系类型。

public class User 
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string FullName { get; set; }

    public List<UserSeries> Series { get; }
}

第二种方法:添加一个额外的关系table`

另一种方法是为每个不同的关系设置不同的table:

public class User 
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string FullName { get; set; }

    public List<UserFavedSeries> FavedSeries { get; }
    public List<UserWatchlistedSeries> WatchlistedSeries { get; }

}

这意味着如果将来您不想添加其他关系,则必须创建另一个 table。

肯定有其他方法可以解决我没有提到的相同问题,并且每种方法都会有一组不同的权衡,您必须分析这些权衡以选择最适合您的方案的解决方案:)