Home > Back-end >  Web API - EF Core 6.0 Create one to many relationship GET with nested relationship
Web API - EF Core 6.0 Create one to many relationship GET with nested relationship

Time:10-24

Using EF Power tools I have the following classes created:

Category.cs

public partial class Category
{
    public Category()
    {
        Folders = new HashSet<Folder>();
        Reports = new HashSet<Report>();
    }

    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public string CategoryDescription { get; set; }
    public string ImagePath { get; set; }

    public virtual ICollection<Folder> Folders { get; set; }
    public virtual ICollection<Report> Reports { get; set; }
}

Folder.cs

public partial class Folder
{
    public Folder()
    {
        Reports = new HashSet<Report>();
    }

    public int FolderId { get; set; }
    public string FolderName { get; set; }
    public int CategoryId { get; set; }
    public string FolderDescription { get; set; }
    public string FolderImagePath { get; set; }

    public virtual Category Category { get; set; }
    public virtual ICollection<Report> Reports { get; set; }
}

The underlying tables are linked one to many with Categoryid. I believe the dbContext.cs was generated correctly based on the table schema.

dbContext.cs

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Category>(entity =>
        {              

            entity.HasKey(e => e.CategoryId)
                .IsClustered(false);

            entity.ToTable("Category");

            entity.Property(e => e.CategoryId)
                .ValueGeneratedNever()
                .HasColumnName("CategoryID");

            entity.Property(e => e.CategoryDescription)
                .HasMaxLength(300)
                .IsUnicode(false);

            entity.Property(e => e.CategoryName)
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.Property(e => e.ImagePath)
                .HasMaxLength(250)
                .IsUnicode(false);              
        } );


        modelBuilder.Entity<Folder>(entity =>
        {
            entity.HasKey(e => e.FolderId)
                .IsClustered(false);

            entity.ToTable("Folder");

            entity.Property(e => e.FolderId)
                .ValueGeneratedNever()
                .HasColumnName("FolderID");

            entity.Property(e => e.CategoryId).HasColumnName("CategoryID");

            entity.Property(e => e.FolderDescription)
                .HasMaxLength(300)
                .IsUnicode(false);

            entity.Property(e => e.FolderImagePath)
                .HasMaxLength(250)
                .IsUnicode(false);

            entity.Property(e => e.FolderName)
                .HasMaxLength(100)
                .IsUnicode(false);

            entity.HasOne(d => d.Category)
                .WithMany(p => p.Folders)
                .HasForeignKey(d => d.CategoryId)
                .OnDelete(DeleteBehavior.ClientSetNull)
                .HasConstraintName("FK_Folder_01");
        });


        OnModelCreatingPartial(modelBuilder);
    }

I then have the following in the controller:

    [HttpGet]
    public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
    {
        return await _context.Categories.ToListAsync();

    }

When I run the WebAPI I see the following:

[ { "categoryId": 1, "categoryName": "Some Name", "folders": [], "reports": [] }, { "categoryId": 2, "categoryName": "Another Name", "folders": [], "reports": [] }, ]

How do I get the related data to populate in the folders array?

I also tried this:

     public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
    {

        var query = (from r in _context.Categories
                     from bu in _context.Folders
                     where r.CategoryId == bu.CategoryId
                     select r
              ).ToListAsync();


        return await query;

CodePudding user response:

I suspect that you application has the loading of relationship to lazy loading.
This means that every relation on the model specified wont be loaded until you ask to specifically see them.

In this specific case you could tell your application to load all the data you need in one go.

[HttpGet]
public async Task<ActionResult<IEnumerable<Category>>> GetCategories()
{
    // note the .Include will tell you application context to load the relation Folders by default
    return await _context.Categories.Include(x => x.Folders).ToListAsync();

}

Here is more information if you want to learn all the way's you could load your relationships by default

  • Related