C# EF Core 模型独立 FK
Posted
技术标签:
【中文标题】C# EF Core 模型独立 FK【英文标题】:C# EF Core Models independent FK 【发布时间】:2021-07-24 18:41:46 【问题描述】:我有一张桌子可以坐。这个点可以有不同的类别。例如:餐厅、酒店、公园。 每个单独的类别都有额外的和不同的细节。 我现在的问题:
是否可以在点表中创建一个独立于类别的列(FK)? 我的意思是当我创建一个类别为餐厅的新地点,而下一个类别是公园类别时。 如果我现在选择一个点,我会从相应的点类别中获得正确的数据
如果可能的话,我如何在 C# EF Core 模型中编写它?
或者这是不可能的,我必须采取其他方式?
提前致谢
以数据库设计为例:
【问题讨论】:
【参考方案1】:不,你不能有一个独立于它所引用的表的 FK 列(category
的表现形式)。您正在寻找的是继承。 EF Core 5 当前支持两种类型的继承 - Table Per Hierarcy (TPH) 和 Table Per Type。两者都可以满足您的目的。
首先,您在继承层次结构中实现实体 Classe,以映射到数据库,派生类表示 Spot
的“类别”:
public abstract class Spot
public Guid Id get; set;
// common spot properties here
// (i.e. props shared by different types of spots like address)
public class Restaurant : Spot
// restaurant specific properties here
public class Park : Spot
// park specific properties here
然后您以两种方式之一将实体映射到单个表 (TPH),该表将使用 discriminator
列到 type
数据库中的每条记录(将被视为您的 category
)和每个派生类型的属性也将包括在内,但仅填充特定类型的记录(即,当 DB 中的记录表示 Restaurant
时,Park
属性将为 null
,反之亦然)。使用此方法可以提高查询性能,但所有特定类型的列都必须可以为空,并且此实现违反了3NF。
TPH 是默认的继承实现,但您可以配置它如何像处理任何其他属性(名称、数据类型)一样处理鉴别器,并为每个派生类型指定要使用的值:
modelBuilder.Entity<Spot>()
.HasDescriminator("Category") // name it what you want
.HasValue<Restaurant>("R") // value for restaurants
.HasValue<Park>("P") // value for parks
;
在 TPT 中,继承层次结构中的每个类型都映射到包含其特定属性的自己的表。派生类型的表使用共享主键来引用它们对应的Spot
记录。查询性能可能会变慢,虽然它不违反 3NF,但手动数据操作操作可能会搞砸事情(例如 Park
和 Restaurant
可以引用相同的 Spot
记录)。
对于此配置,只需将实体层次结构中的每个类型映射到其自己的表:
modelBulider.Entity<Restaurant>().ToTable("Restaurant");
modelBuilder.Entity<Park>().ToTable("Park");
对于这两种实现,您都可以正常实现DbSet
属性:
public DbSet<Spot> Spots get; set;
public DbSet<Restaurant> Restaurants get; set;
public DbSet<Park> Parks get; set;
您可以使用.OfType<T>()
从Spots
获取特定类型的Spot
s
var parks = dbContext.Spots.OfType<Park>();
因此,如果包含Spot
s DbSet<T>
,则不需要Restaurants
或Parks
DbSet<T>
s。或者,如果您为派生类型包含 DbSet<T>
s,则 Spots
是可选的。
我鼓励您以两种方式对实体进行建模,以了解 EF 如何对数据库进行建模并选择您喜欢的方式。
https://docs.microsoft.com/en-us/ef/core/modeling/inheritance
【讨论】:
非常感谢我采用了 TPT 方法,效果如我所愿以上是关于C# EF Core 模型独立 FK的主要内容,如果未能解决你的问题,请参考以下文章
如何在不将实例模型添加到数据库的情况下向实体模型添加FK约束?