2
votes

I have the following Entities

public class A
{
    public int AId {get; set;}
}

public class B
{
    public int BId {get; set;}
    public virtual A Child1 {get; set;}
    public virtual A Child2 {get; set;}
}

with the following configuration

modelBuilder.Entity<B>()
            .HasRequired(x => x.Child1)
            .WithMany()
            .Map(x => x.MapKey("Child1Id"))

modelBuilder.Entity<B>()
            .HasRequired(x => x.Child2)
            .WithMany()
            .Map(x => x.MapKey("Child2Id"))

For some reason Entity Framework does not lazy load the Child1 or Child2 properties when requesting an Entity of object B. That is

var b1 = context.Bs.FirstOrDefault();
Assert.IsNull(b.Child1) // true
Assert.IsNull(b.Child2) // true

but it works if i explcitly loads them.

var b2 = context.Bs.Include(x => x.Child1).Include(x => x.Child2).FirstOrDefault();
Assert.NotNull(b2.Child1) // true
Assert.NotNull(b2.Child2) // true

Does anyone know why the properties does not get lazy loaded?

EDIT

It seems that

context.Bs.FirstOrDefault()

returns the entity itself and not a proxy type. This indicates that the property ProxyCreationEnabled is false but I have double checked it and it is set to true.

EDIT 2

Ok, finally found the problem. I had set Bs constructor to private which of course makes it impossible to extend the object with a proxy class. And hence, the navigation properties where set to null.

1
They have been lazy loaded...... because they don't exist (the lazy part)Callum Linington
Read this excellent article on loading entities from msdnCallum Linington
No the properties exists, it works if I explicitly includes them in the query.olif
Have you enabled lazy loading in EF options?Nick Louloudakis
Yes it is enabled.olif

1 Answers

1
votes

I have modified your code so that working with lazy loading. just copy paste and everything should be fine.

Check the b1 with VS before the write line, you will see the lazy loaded objects and do not scare from the long entity name this because I have enabled the proxy creation.

 public class Program
 {
     public static void Main(string[] args)
     {
         Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());

         using (var myDbContext = new MyDbContext("DefaultConnection"))
         {
             var a1 = new A();
             var a2 = new A();

             var b1 = new B
             {
                 Child1 = a1,
                 Child2 = a2
             };

             myDbContext.Bs.Add(b1);
             myDbContext.SaveChanges();
         }

         using (var myDbContext = new MyDbContext("DefaultConnection"))
         {
             var b1 = myDbContext.Bs.FirstOrDefault();
             b1.ToString();
             Console.WriteLine(b1.ToString());
         }
     }

     public class A
     {
         public int AId { get; set; }
     }

     public class B
     {
         public int BId { get; set; }
         public virtual A Child1 { get; set; }
         public virtual A Child2 { get; set; }
     }

     public class MyDbContext : DbContext
     {
         public DbSet<A> As { get; set; }
         public DbSet<B> Bs { get; set; }

         protected override void OnModelCreating(DbModelBuilder modelBuilder)
         {
             modelBuilder.Entity<B>()
                 .HasRequired(x => x.Child1)
                 .WithMany()
                 .Map(x => x.MapKey("Child1Id")).WillCascadeOnDelete(false);

             modelBuilder.Entity<B>()
                 .HasRequired(x => x.Child2)
                 .WithMany()
                 .Map(x => x.MapKey("Child2Id")).WillCascadeOnDelete(false);

             base.OnModelCreating(modelBuilder);
         }

         public MyDbContext(string connectionString)
           : base("name=" + connectionString)
         {
             this.Configuration.LazyLoadingEnabled = true;
             this.Configuration.ProxyCreationEnabled = true;
         }
     }
 }