c# - Entity Framework Core:两个实体之间的多个一对多关系
问题描述
我尝试通过让翻译模型运行
public class Item
{
public Item
{
TextTranslationID = Guid.NewGuid();
DescriptionTranslationID = Guid.NewGuid();
TextTranslations = new HashSet<Translation>();
DescriptionTranslations = new HashSet<Translation>();
}
[Key]
public int ItemID { get; set; }
public Guid TextTranslationID { get; set; }
public Guid DescriptionTranslationID { get; set; }
[ForeignKey(nameof(TextTranslationID))]
public virtual ICollection<Translation> TextTranslations { get; set; }
[ForeignKey(nameof(DescriptionTranslationID))]
public virtual ICollection<Translation> DescriptionTranslations { get; set; }
}
和翻译实体
public class Translation
{
public Translation()
{
UniqueTranslationID = Guid.NewGuid();
}
[Key]
public Guid UniqueTranslationID { get; set; }
/// <summary>
/// The translation id, keyed with the language.
/// </summary>
[Required]
public Guid TranslationID { get; set; }
/// <summary>
/// The 2-char language code. eg "en", "es"
/// </summary>
[Required]
[StringLength(2, MinimumLength = 2)]
public string Language { get; set; }
[Required]
[StringLength(2000)]
public string Text { get; set; }
}
这是一个单向关系,因此我不需要也不想要 Translation.Parent 或 Translation 实体上的类似内容。实体只是翻译的Item
众多消费者之一,因此这里不需要逆属性。如您所见,该项目与翻译有两个连接。
我已经尝试了很多与模型构建器的组合来在 sql 中实现这样一个简单的任务,但是生成的 sql 脚本总是想在翻译表中添加一个 DescriptionTranslationID 和 TextTranslationID。
...
migrationBuilder.CreateTable(
name: "Translations",
columns: table => new
{
UniqueTranslationID = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TranslationID = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Language = table.Column<string>(type: "nvarchar(2)", maxLength: 2, nullable: false),
Text = table.Column<string>(type: "nvarchar(2000)", maxLength: 2000, nullable: false),
DescriptionTranslationID = table.Column<int>(type: "int", nullable: true),
TextTranslationID = table.Column<int>(type: "int", nullable: true)
},
...
如何设置从项目到翻译的两个一对多关系?非常感谢!
解决方案
这是解决方案的完整示例。
给定两个实体(问题、答案),它们需要多个本地化(Localization)而不需要反向导航。
public class CatalogQuestion
{
public CatalogQuestion()
{
TextTranslationID = Guid.NewGuid();
DescriptionTranslationID = Guid.NewGuid();
TextTranslations = new HashSet<Translation>();
DescriptionTranslations = new HashSet<Translation>();
}
[Key]
public int CatalogQuestionID { get; set; }
public Guid TextTranslationID { get; set; }
public Guid DescriptionTranslationID { get; set; }
///
public virtual ICollection<Translation> TextTranslations { get; set; }
public virtual ICollection<Translation> DescriptionTranslations { get; set; }
}
public class CatalogAnswer
{
public CatalogAnswer()
{
TextTranslationID = Guid.NewGuid();
DescriptionTranslationID = Guid.NewGuid();
TextTranslations = new HashSet<Translation>();
DescriptionTranslations = new HashSet<Translation>();
}
[Key]
public int CatalogAnswerID { get; set; }
public Guid TextTranslationID { get; set; }
public Guid DescriptionTranslationID { get; set; }
///
public virtual ICollection<Translation> TextTranslations { get; set; }
public virtual ICollection<Translation> DescriptionTranslations { get; set; }
}
/// <summary>
/// Allows every entity that has a <see cref="Guid"/> to have a translation.
/// </summary>
public class Translation
{
public Translation()
{
UniqueTranslationID = Guid.NewGuid();
}
/// <summary>
/// Used for direct addressing this single translation.
/// </summary>
[Key]
public Guid UniqueTranslationID { get; set; }
/// <summary>
/// The translation id, keyed with the language.
/// Must not be an empty guid.
/// </summary>
[Required]
public Guid TranslationID { get; set; }
/// <summary>
/// The 2-char language code. eg "de", "en"
/// </summary>
[Required]
[StringLength(2, MinimumLength = 2)]
public string Language { get; set; }
[Required]
[StringLength(2000)]
public string Text { get; set; }
}
这是模型构建器的 FluentApi,将这些东西粘合在一起:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Translation>(entity => {
entity.HasIndex(e => new { e.TranslationID, e.Language }).IsUnique();
});
modelBuilder.Entity<CatalogQuestion>(entity => {
entity.HasMany(e => e.TextTranslations).WithOne().HasForeignKey(e => e.TranslationID).HasPrincipalKey(e => e.TextTranslationID).HasConstraintName("FK_Translations_CatalogQuestionsText_TranslationID");
entity.HasMany(e => e.DescriptionTranslations).WithOne().HasForeignKey(e => e.TranslationID).HasPrincipalKey(e => e.DescriptionTranslationID).HasConstraintName("FK_Translations_CatalogQuestionsDescription_TranslationID");
});
modelBuilder.Entity<CatalogAnswer>(entity => {
entity.HasMany(e => e.TextTranslations).WithOne().HasForeignKey(e => e.TranslationID).HasPrincipalKey(e => e.TextTranslationID).HasConstraintName("FK_Translations_CatalogAnswersText_TranslationID");
entity.HasMany(e => e.DescriptionTranslations).WithOne().HasForeignKey(e => e.TranslationID).HasPrincipalKey(e => e.DescriptionTranslationID).HasConstraintName("FK_Translations_CatalogAnswersDescription_TranslationID");
});
}
由于我们正在创建两个非主键之间的关系,因此我们需要在 FlientApi 中定义它,否则迁移将与注释和 FluentApi 混淆。
推荐阅读
- html - 为什么 flexbox 容器将列表项拆分为两行?
- r - 将数据拟合到 R 中的逻辑函数
- python - 使用 Python 从字符串解析 XML
- html - 在具有指定尺寸的 div 内部时,图像宽度和最大宽度有什么区别?
- mysql - docker 卷已删除,但似乎已缓存
- python - 遍历 csv 文件中的列以获取请求
- c - 错误:14089086:SSL 例程:ssl3_get_client_certificate:证书验证失败
- r - ggplot2没有找到对象+图例问题
- dart - Mac OS 上的 Protobuf dart 生成找不到 protoc-gen-dart
- python-3.x - 如何将 Web 应用程序上传到生产服务器?