EF Core 8配置:将同类型值对象多集合属性存入单表
EF Core 8 配置同一表存储多类型邮箱地址
简化后模型代码
// 模型已简化以突出核心逻辑 public class Notification { public Guid Id { get; set; } public EmailAddress From { get; set; } public ICollection<EmailAddress> To { get; set; } public ICollection<EmailAddress> Cc { get; set; } public ICollection<EmailAddress> Bcc { get; set; } public string Subject { get; set; } public string Body { get; set; } } public class EmailAddress { // 注:需补充主键Id,否则EF Core无法完成实体映射 public Guid Id { get; set; } public string DisplayName { get; set; } public string Address { get; set; } }
需求与偏好表结构
需将所有邮箱地址存入同一个emailaddresses表,通过鉴别器字段区分From/To/Cc/Bcc类型,偏好表结构如下:
notification表
| id | subject | body |
|---|
emailaddresses表
| id | notification_id | address | display_name | discriminator |
|---|
EF Core 8 配置实现
在DbContext的OnModelCreating方法中添加以下Fluent API配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Notification实体 modelBuilder.Entity<Notification>(entity => { entity.ToTable("notification"); entity.HasKey(n => n.Id); entity.Property(n => n.Id).HasColumnName("id"); entity.Property(n => n.Subject).HasColumnName("subject"); entity.Property(n => n.Body).HasColumnName("body"); // 配置From一对一关联,设置鉴别器值为"From" entity.HasOne(n => n.From) .WithOne() .HasForeignKey<EmailAddress>("NotificationId") .IsRequired(false); // 配置To集合关联,设置鉴别器值为"To" entity.HasMany(n => n.To) .WithOne() .HasForeignKey("NotificationId") .IsRequired(false) .Metadata.DiscriminatorValue = "To"; // 配置Cc集合关联,设置鉴别器值为"Cc" entity.HasMany(n => n.Cc) .WithOne() .HasForeignKey("NotificationId") .IsRequired(false) .Metadata.DiscriminatorValue = "Cc"; // 配置Bcc集合关联,设置鉴别器值为"Bcc" entity.HasMany(n => n.Bcc) .WithOne() .HasForeignKey("NotificationId") .IsRequired(false) .Metadata.DiscriminatorValue = "Bcc"; }); // 配置EmailAddress实体,采用TPH(单表存储所有关联类型)策略 modelBuilder.Entity<EmailAddress>(entity => { entity.ToTable("emailaddresses"); entity.HasKey(e => e.Id); entity.Property(e => e.Id).HasColumnName("id"); entity.Property(e => e.Address).HasColumnName("address"); entity.Property(e => e.DisplayName).HasColumnName("display_name"); // 配置鉴别器字段 entity.Property<string>("Discriminator") .HasColumnName("discriminator") .HasMaxLength(20); // 配置关联Notification的外键字段 entity.Property<Guid>("NotificationId") .HasColumnName("notification_id"); }); }
关键说明
- 原
EmailAddress模型缺少主键Id,必须补充才能让EF Core正确生成表结构 - 采用EF Core的**TPH(表每层次)**映射策略,通过
Discriminator字段区分不同类型的邮箱地址 - 若业务中不需要
DisplayName字段,可直接移除模型属性及对应配置代码
内容的提问来源于stack exchange,提问作者Hamlet Hakobyan
相关产品推荐
相关产品推荐

