Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One To Many returns empty array

I'm trying to connect two objects with one-to-many relationship, Workplace can hold multiple People, while one Person can only have one Workplace.

When I execute this code snippet and check to see the results, p1 has properly assigned w1 as the p1.Workplace, but the list of people of the w1.employees is always empty.

Do I have to manually add p1 to w1.Employees even after I assigned w1 to p1.Workplace?

SeedData.cs (code snippet)

var w1 = new Workplace
{
   EntryCode = "1111"
   //[...] other data I cut out for brievity
};
context.Workplaces.Add(w1);

Person p1 = new Person
{
    Name = "Spencer",
    Workplace = w1
   //[...] other data I cut out for brievity
};
context.Person.Add(p1)
context.SaveChanges();

Workplace.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Counsel.Models
{
    [Table("Workplace")]
    public class Workplace
    {
        [Column("WorkplaceId")]
        public int WorkplaceId {get;set;}

        [Column("EntryCode")]
        public string EntryCode {get;set;}

        [Column("ConfirmationCode")]
        public string ConfirmationCode {get;set;}

        [Column("Employees")]
        public ICollection<Person> Employees {get;set;}
    }
}

Person.cs

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace Counsel.Models
{
    public class Person
    {
        [Column("PersonId")]
        public int PersonId {get;set;}

        [Column("Image")]
        public string Image {get;set;}

        [Column("FName")]
        public string FName { get; set; }

        [Column("LName")]
        public string LName {get;set;}

        [Column("Role")]
        public string Role {get;set;}

        [Column("Email")]
        public string Email {get;set;}

        [Column("Password")]
        public string Password {get;set;}

        public Workplace Workplace {get;set;} = new Workplace();
        public ICollection<ChatPerson> Chats {get;set;}
    }
}

DataContext.cs

using Counsel.Models;
using Microsoft.EntityFrameworkCore;

namespace Counsel.Models {
    public class DataContext : DbContext
    {
        public DataContext(DbContextOptions<DataContext> opts): base(opts){}

        public DbSet<Person> People {get;set;}
        public DbSet<Workplace> Workplaces {get;set;}


        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {

            modelBuilder.Entity<Person>((item)=>{
                item.HasKey(p => p.PersonId);
                item.HasOne<Workplace>(p => p.Workplace).WithMany(w => w.Employees).OnDelete(DeleteBehavior.SetNull);
            });


            modelBuilder.Entity<Workplace>((item)=>{
                item.HasKey(p => p.WorkplaceId);
                item.HasMany<Person>(w => w.Employees).WithOne(p => p.Workplace).OnDelete(DeleteBehavior.Cascade);
            });
        }
    }
}

WorkplaceController.cs (code snippet)

[HttpGet("{id}")]
        public Workplace GetWorkplace(int id)
        {
           return context.Workplaces
                .Where(c => c.WorkplaceId == id)
                .Include(c => c.Employees).ThenInclude(c => c.Workplace)
                .FirstOrDefault();

        }

GetWorplace() output

[
  {
    "workplaceId": 1,
    "entryCode": "1111",
    "confirmationCode": "1111",
    "employees": [

    ]
  }
]

As you can see, the "employees" array is empty, even though p1 should be there.

like image 466
kzmijak Avatar asked Nov 02 '25 07:11

kzmijak


1 Answers

The problem is caused by the reference navigation property initializer:

public Workplace Workplace { get; set; } = new Workplace(); // <--

Never do that - it confuses EF navigation property fixup and leads to unexpected runtime behaviors.

Note that initializing collection navigation properties is ok, although not required. It's because null in reference navigation property have a special meaning and really provides a link to the principal entity, which may or may not contain collection of dependent entities.

Shortly, remove the initializer

public Workplace Workplace { get; set; }

and the issue will be solved.

like image 51
Ivan Stoev Avatar answered Nov 03 '25 21:11

Ivan Stoev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!