我正在做一个需要多对多关系的项目。我知道为了做到这一点,您应该创建联接表。
在我的项目中,我们有用户,系列和剧集。为了简单起见,我们将忽略这些情节。用户拥有喜欢的系列和监视列表。
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 Core抱怨:
无法在“ User.WatchList”和“ UserSeries.User”之间创建关系,因为“ User.FavoriteSeries”和“ UserSeries.User”之间已经存在关系。导航属性只能参与单个关系。
我尝试制作一个UserFavoriteSeriesConfiguration
和UserWatchListConfiguration
,并给它们分别指定表名,但这很丑陋,导致代码重复和许多额外的配置类(特别是因为带有情节等)。我也有这个设置),最糟糕的是:它仍然无法正常工作...
是否有解决此问题的简单方法?最坏的情况是,我必须创建联接实体(而不是UserSeries
才能创建UserFavoriteSeries
),但这与我在上几段中描述的否定词相比要翻倍:很多额外的类和重复的代码
答案 0 :(得分:1)
“收藏”系列与“关注列表”系列是不同的关系,因此,在将数据存储到数据库中时,您需要以某种方式区分这两种不同类型的关系。
现在,您只有一个表可以映射这两种关系,这就是发生的情况:
您看到问题了吗? UserSerie
表中有重复的行,可能是因为Diego
已将Fav
标记为Bojack
,并且他也将其添加到了Watchlist
中。但是,无法分辨哪一行代表Fav
关系,哪一行代表Watchlisted
关系。
第一种方法:向UserSerie
添加一个附加属性作为区分符
一种方法是添加新属性(数据库表列)以存储User
和Serie
之间的关系类型。
现在您可以清楚地看到每一行所代表的关系类型: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; }
}
第二种方法:添加其他关系表`
另一种方法是为每个不同的关系使用不同的表:
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; }
}
这意味着如果将来您不想添加其他关系,则必须创建另一个表。
肯定有其他方法可以解决我没有提到的相同问题,并且每种方法都将具有不同的权衡,您必须分析这些权衡,以便选择最适合您的方案的解决方案:)