EF Core Eager loading returns null

Viewed 448

I have an Entity Patient and an Entity User. Between them is a one to one relationship.

User:

public class User
    {      
        public long Id { get; set; }

        public string Name { get; set; }

        public string Username { get; set; }      
                ......
        [JsonIgnore]
        public   Patient Patient { get; set; }
   }

Patient:

public class Patient
    {
        public long Id { get; set; }

        public long UserId { get; set; }

        public  User User { get; set; }
    }

When I try to extract a patient from the Database I got a null reference for the user.

DataContext:
 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Patient>()
                .HasOne(b => b.User)
                .WithOne(i => i.Patient)
                .HasForeignKey<Patient>(b => b.UserId);}

                 ....
    }

PatientRepo:

public IEnumerable<Patient> GetAll()
        {
            var patients = _dataContext.Patients.Include(x=>x.User);

            return patients;
        }

Controller Method:

  [HttpGet("patients")]
        public IActionResult GetAllPatient()
        {
            return Ok(_patientRepository.GetAll());
        }

Migrations : USER

migrationBuilder.CreateTable(
                name: "Users",
                columns: table => new
                {
                    Id = table.Column<long>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    Name = table.Column<string>(nullable: true),
                    Username = table.Column<string>(nullable: true),
                    PasswordHash = table.Column<byte[]>(nullable: true),
                    PasswordSalt = table.Column<byte[]>(nullable: true),
                    BirthDate = table.Column<DateTime>(nullable: false),
                    GenderId = table.Column<int>(nullable: true),
                    UserRoleId = table.Column<long>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Users", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Users_Genders_GenderId",
                        column: x => x.GenderId,
                        principalTable: "Genders",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Users_UserRoles_UserRoleId",
                        column: x => x.UserRoleId,
                        principalTable: "UserRoles",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

PATIENTS

migrationBuilder.CreateTable(
                name: "Patients",
                columns: table => new
                {
                    Id = table.Column<long>(nullable: false)
                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
                    UserId = table.Column<long>(nullable: false),
                    DoctorId = table.Column<long>(nullable: true),
                    CaregiverId = table.Column<long>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Patients", x => x.Id);
                    table.ForeignKey(
                        name: "FK_Patients_Caregivers_CaregiverId",
                        column: x => x.CaregiverId,
                        principalTable: "Caregivers",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Patients_Doctors_DoctorId",
                        column: x => x.DoctorId,
                        principalTable: "Doctors",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Patients_Users_UserId",
                        column: x => x.UserId,
                        principalTable: "Users",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Cascade);
                });

What I receive on Postman :

 {
        "id": 1,
        "userId": 3,
        "user": null
}

On Debug enter image description here

One Wierd thing that I notice is that Mysql sees this relationship as many to one enter image description here

3 Answers

You should set DeleteBehavior when create the relation between two entity:

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Patient>()
            .HasOne(b => b.User)
            .WithOne()
            .HasForeignKey<Patient>(b => b.UserId)
            .OnDelete(DeleteBehavior.Restrict);

}

So apparently there are to libraries which provide functionalities for the method .Include() : Microsoft.EntityFrameworkCore (good one) and System.Data.Entity ( bad one); I choose the bad one and I got no syntax error or runtime error just a bad functionality.

Ok, you need to use .ToList() in your query.

      var patients = _dataContext.Patients.Include(x=>x.User).ToList();
Related