ef core how to get data from different tables with foreign keys at once? (DB first)

1.3k views Asked by At

I have two tables in my project, "educator" and "educator license".

The educator license is depended to the educator table with foreign key. (DB first)

Foreign keys with id in my db: (educator can have N license)

enter image description here

my educator model like:

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; }
}

my educator license model like:

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

My 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);
    });
}

and I got that exception: enter image description here

I want it to getting the educator license table with it when getting the educator table.

I think I can do this at the business layer, by going to the database twice with lazy load.

Is there a way to getting two tables connected with foreign to each other at once?

2

There are 2 answers

0
atiyar On BEST ANSWER

You are configuring the foreign-key in wrong way. The following code -

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

should be -

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

Then if you query like -

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

you'll get a list of Educator along with their EducatorLicense list.

TIP :
To better reflect the fact that its a collection of something (and hence, the Many end of the relationship), you should rename the EducatorLicense property in the Educator class to its plural form EducatorLicenses.

0
Serge On

Try to replace your db context with this

            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");
                });

Add Educator to your EducatorLicense

 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; }
}

Rename EducatorLicense of Educator class to EducatorLicenses

public List<EducatorLicense> EducatorLicenses { get; set; }