EF Core one to one to zero relationship not returning data in result

asp.net-core ef-code-first ef-core-2.2 entity-framework-core

Question

I'm currently in the process of migrating an existing database design into a new application using EF Core 2.2.1 with code first migrations. Our current design has a primary table which then can have multiple sub tables with the same, shared primary key. I've looked at this similar question and tried to replicate the answer there, but haven't had much luck in having the data show in the result.

The simplified schema looks a bit like the following:

public class Root
{
    public enum SubEntityType
    {
        A,
        B,
        C,
        D
    }

    public Guid Id { get; set; }

    public SubEntityType Type { get; set; }


    public virtual TypeA A { get; set; }
    public virtual TypeB B { get; set; }
    public virtual TypeC C { get; set; }
    public virtual TypeD D { get; set; }

}

public class TypeA
{
    public Guid Id { get; set; }

    public virtual Root Root { get; set; }

    public int A { get; set; }
}

public class TypeB
{
    public Guid Id { get; set; }
    public virtual Root Root { get; set; }

    public Guid B { get; set; }
}

public class TypeC
{
    public Guid Id { get; set; }
    public virtual Root Root { get; set; }

    public string C { get; set; }
}

public class TypeD
{
    public Guid Id { get; set; }
    public virtual Root Root { get; set; }

    public bool D { get; set; }
}

Then I've set up the relationships using fluent api as follows:

builder.Entity<Models.Root>()
    .HasOne( e => e.A )
    .WithOne( e => e.Root )
    .HasForeignKey<Models.TypeA>( e => e.Id );

builder.Entity<Models.Root>()
    .HasOne( e => e.B )
    .WithOne( e => e.Root )
    .HasForeignKey<Models.TypeB>( e => e.Id );

builder.Entity<Models.Root>()
    .HasOne( e => e.C )
    .WithOne( e => e.Root )
    .HasForeignKey<Models.TypeC>( e => e.Id );

builder.Entity<Models.Root>()
    .HasOne( e => e.D )
    .WithOne( e => e.Root )
    .HasForeignKey<Models.TypeD>( e => e.Id );

It seems to work great up until I try to add data. I create the root entry with some dummy data. In root table:

Id                                      Type
6f0f24cf-fbd7-4b4d-8059-0810daaf5460    1

In TypeA table:

Id                                      A
6f0f24cf-fbd7-4b4d-8059-0810daaf5460    12

Everything inserts fine and looks good. When I query this like so:

var result = ctx.Root.First();

I get the following result (apologies for formatting, tried to make it a bit nicer):

Name                Value
result              {Test.Models.Root}
    A               null
    B               null
    C               null
    D               null
    Id              {6f0f24cf-fbd7-4b4d-8059-0810daaf5460}
    Type            B

Shouldn't A be populated with the Test.Models.TypeA object with the A set to 12? Is this an optimisation that EF does and I need to load A on demand or have I set up the relationship incorrectly? Alternatively, is my approach wrong here and I should be doing this differently?

1
0
1/22/2019 11:55:48 AM

Accepted Answer

In Entity Framework Core, virtual navigation properties are not loaded automatically unless you Configure Lazy Loading or use Eager Loading with Include.

So write your query as follows:

var result = ctx.Root.Include(r => r.TypeA).Include(r => r.TypeB)
                     .Include(r => r.TypeC).Include(r => r.TypeD).FirstOrDefault();

Now Root will have TypeA, TypeB, TypeC and TypeD associated with it.

2
1/22/2019 12:47:15 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow