ef core 如何一次从具有外键的不同表中获取数据? (数据库优先)

Posted

技术标签:

【中文标题】ef core 如何一次从具有外键的不同表中获取数据? (数据库优先)【英文标题】:ef core how to get data from different tables with foreign keys at once? (DB first) 【发布时间】:2021-05-09 21:34:06 【问题描述】:

我的项目中有两个表,“教育者”和“教育者许可证”。

教师许可证依赖于具有外键的教师表。 (数据库优先)

我的数据库中带有 id 的外键: (教育者可以有N个执照)

我的教育者模型如下:

public class Educator

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [JsonIgnore]
    public int id  get; set; 
    [JsonIgnore]
    public int CompanyId  get; set; 
    public string PublicId  get; set; 
    public string Name  get; set; 
    public string PhoneNumber  get; set; 
    public int Password  get; set; 
    public bool Gender  get; set; 
    public string AdminNote  get; set; 
    public List<EducatorLicense> EducatorLicense  get; set; 
    public bool Status  get; set; 
    public TimestampsModel Timestamps  get; set; 

我的教育者许可模式,例如:

public class EducatorLicense

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int id  get; set; 
    [JsonIgnore]
    public int EducatorId  get; set; 
    public string LicenseType  get; set; 

我的 DbContext:

protected override void OnModelCreating(ModelBuilder model)

    model.Entity<Educator>(builder =>
    
        builder.ToTable("educators");
        builder.Property(p => p.id)
            .ValueGeneratedOnAdd();
        builder.OwnsOne(c => c.Timestamps,
            a =>
            
                a.Property(p => p.CreatedAt).HasColumnName("createdAt");
                a.Property(p => p.UpdatedAt).HasColumnName("updatedAt");
            );

        builder.HasOne(d => d.EducatorLicense)
            .WithMany()
            .HasForeignKey(d => d.Id)
            .OnDelete(DeleteBehavior.ClientSetNull)
            .HasConstraintName("educatorlicenses_educatorid_foreign");
    );

    model.Entity<EducatorLicense>(builder =>
    
        builder.Property(p => p.id)
            .ValueGeneratedOnAdd();
        builder.HasKey(c => c.id);
    );

我得到了那个例外:

我希望它在获取教育者表时也能获得教育者许可表。

我想我可以在业务层做到这一点,通过延迟加载两次访问数据库。

有没有办法让两个表同时连接到外部?

【问题讨论】:

【参考方案1】:

您以错误的方式配置外键。以下代码-

builder.HasOne(d => d.EducatorLicense)
    .WithMany()
    .HasForeignKey(d => d.Id)
    .OnDelete(DeleteBehavior.ClientSetNull)
    .HasConstraintName("educatorlicenses_educatorid_foreign");

应该是-

builder.HasMany(d => d.EducatorLicense)
    .WithOne()
    .HasForeignKey(d => d.EducatorId)
    .OnDelete(DeleteBehavior.ClientSetNull)
    .HasConstraintName("educatorlicenses_educatorid_foreign");

那么如果你像这样查询 -

var educatorList = myDbContext.Educators.Include(p=> p.EducatorLicense).ToList();

您将获得Educator 的列表以及他们的EducatorLicense 列表。

提示: 为了更好地反映它是一个集合的事实(因此,关系的Many 结束),您应该将Educator 类中的EducatorLicense 属性重命名为它的复数形式EducatorLicenses

【讨论】:

【参考方案2】:

尝试用这个替换你的数据库上下文

            modelBuilder.Entity<Educator>(entity =>
            
                entity.HasOne(d => d.Educator)
                    .WithMany(p => p.EducatorLicences)
                    .HasForeignKey(d => d.EducatorId)
                    .OnDelete(DeleteBehavior.ClientSetNull);

                  );

               builder.OwnsOne(c => c.Timestamps,
                a =>
                
                    a.Property(p => p.CreatedAt).HasColumnName("createdAt");
                    a.Property(p => p.UpdatedAt).HasColumnName("updatedAt");
                );

将教育者添加到您的教育者许可中

 public class EducatorLicense

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

    public int id  get; set; 
    [JsonIgnore] public int EducatorId  get; set; 
    public Educator Educator  get; set; 
    public string LicenseType  get; set; 


将 Educator 类的 EducatorLicense 重命名为 EducatorLicenses

public List<EducatorLicense> EducatorLicenses  get; set; 

【讨论】:

以上是关于ef core 如何一次从具有外键的不同表中获取数据? (数据库优先)的主要内容,如果未能解决你的问题,请参考以下文章

休眠。如何将条目添加到具有来自 Hibernate 中 2 个不同表的 2 个外键的表中?

从具有三个外键的表中选择一个表[关闭]

如何从具有两个外键的表中访问列?

要在 EF Core 中添加没有外键的导航属性,使用 .NET Core Web API 进行 DB-first 迁移

如何在 SAP ASE Sybase 16 中从具有外键的表中删除行

如何将具有外键的 NOT NULLABLE 列添加到已包含数据的现有表中?