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 列)来存储 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; }
}
第二种方法:添加一个额外的关系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。
肯定有其他方法可以解决我没有提到的相同问题,并且每种方法都会有一组不同的权衡,您必须分析这些权衡以选择最适合您的方案的解决方案:)
我正在做一个需要多对多关系的项目。我知道为了做到这一点,您应该创建 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 列)来存储 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; }
}
第二种方法:添加一个额外的关系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。
肯定有其他方法可以解决我没有提到的相同问题,并且每种方法都会有一组不同的权衡,您必须分析这些权衡以选择最适合您的方案的解决方案:)