在使用 EF Core 8.0.7 和代码优先方法的应用程序中,我有一个内容表,其中包含基于语言的应用程序内容。 Content 表通过 ParentId 引用父实体中的记录,每个 Content 记录由 Key、ParentId 和 LanguageId 的组合唯一标识。
我想向具有关联内容的所有实体模型添加导航属性。具体来说,我希望导航属性看起来像这样:
public virtual ICollection<Content>? Contents { get; set; }
这是我的内容模型
public class Content : EntityBase
{
[MaxLength(40)]
public string Key { get; set; }
[MaxLength(2000)]
public string Value { get; set; }
public Guid ParentId { get; set; }
public Guid LanguageId { get; set; }
[MaxLength(40)]
public string ParentTable { get; set; }
public virtual Language? Language { get; set; }
}
鉴于 EF Core 通过外键管理导航属性,我应该如何配置这些关系?我是否应该以特定方式设置导航属性以确保内容记录与其父实体正确关联?我是否应该遵循任何特定的 EF Core 配置或约定?
注意:我知道有关此主题的相关帖子,但它们没有解决我的问题。
简短的回答:不。避免这种非名词化设计。虽然它看起来简单紧凑,但您无法利用单个内容表与其他相关表之间的 FK 关系,同样,数据库也无法强制引用完整性。由于缺乏索引或复杂的索引,而且更重要的是“所有”内容记录都放置在 1 个表中,这也是性能最差的选项。如果您在 10 个相关实体中有 1M 内容行,则使用跨单独内容表的专用 FK 和索引(此处 100k,那里 250k,C 型 25k 等)进行查询将比始终跨 1M 行进行查询性能更高。 更好:
public abstract class Content : EntityBase
{
[MaxLength(40)]
public string Key { get; set; }
[MaxLength(2000)]
public string Value { get; set; }
public Guid LanguageId { get; set; }
[MaxLength(40)]
public virtual Language? Language { get; set; }
}
public class CompanyContent : Content
{
public virtual Company Company { get; set; }
}
public class Company : EntityBase
{
// ...
public virtual ICollection<CompanyContent> Contents { get; } = [];
}
使用TPC或TPT继承模型。我倾向于使用 TPC 来实现更简单、更快的连接,但如果您需要跨所有
内容进行查询(尽管存在关系),那么 TPT 可能会更有用。 即使您最终得到 10 倍的表数量,每个表仅与 FK 及其支持的类型不同,这并不重要。数据库的“成本”是额外的表定义,但总行数的数据存储成本保持不变。查询任何一个较小表的内容并不涉及查询整个内容集,只涉及与该表相关的内容行。