EF核心:同一实体之间的多对多关系

问题描述 投票:1回答:1

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

在我的项目中,我们有用户,系列和剧集。为了简单起见,我们将忽略这些情节。用户有喜欢的系列和监视列表。

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; }
}

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

现在,我正在尝试为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核心投诉:

无法在'User.WatchList'和'UserSeries.User'之间建立关系,因为'User.FavoriteSeries'和'UserSeries.User'之间已经存在关系。导航属性只能参与单个关系。

我尝试制作一个UserFavoriteSeriesConfiguration和一个UserWatchListConfiguration,并给它们分别指定表名,但这很丑陋,使得代码重复,并产生了许多额外的配置类(特别是因为带有情节等。我也有这种设置) ),最糟糕的是:它仍然无法正常工作...

是否有解决此问题的简单方法?最坏的情况下,我将必须创建连接实体(而不是UserSeries才能创建UserFavoriteSeries),但这与我在上几段中所描述的否定词相比要翻倍:很多额外的类和重复的代码。

.net entity-framework .net-core ef-code-first ef-core-3.1
1个回答
1
投票

“收藏”系列与“关注列表”系列是不同的关系,因此,在将数据存储到数据库中时,您需要以某种方式能够区分出这两种不同类型的关系。

现在,您只有一个表可以映射两个关系,这就是发生的情况:

Situation now

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

第一种方法:向UserSerie添加一个附加属性作为鉴别符

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

Add attribute approach

您现在可以清楚地看到每一行代表的关系是什么类型: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; }
}

第二种方法:添加一个附加关系表`

另一种方法是为每个不同的关系使用不同的表:

enter image description here

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; }

}

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

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

© www.soinside.com 2019 - 2024. All rights reserved.