Eric
Eric

Reputation: 6016

Navigation properties not being loaded from database

I'm having a problem loading entities from an EF 4.3 Code First database. I've simplified my code down to this working sample code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity.Infrastructure;

namespace CodeFirst {
    class Program {
        static void Main(string[] args) {
            Database.SetInitializer(new DropCreateDatabaseAlways<Context>());
            Database.DefaultConnectionFactory = new SqlCeConnectionFactory("System.Data.SqlServerCe.4.0");

            using (Context context = new Context()) { 
                A a = new A { B = new B { Foo = 1 } };
                context.As.Add(a);
                context.SaveChanges();
                Print(context); // B has ID=1, Foo=1
            }

            using (Context context = new Context()) { 
                Print(context); // B is null
            }

            Console.ReadLine();
        }

        public static void Print(Context context) {
            A a = context.As.Single();
            Console.WriteLine("A: ID=" + a.Id);
            if (a.B == null) {
                Console.WriteLine("B: null");
            }
            else { 
                Console.WriteLine("B: ID=" + a.B.Id + ", Foo=" + a.B.Foo);
            }
        }
    }

    class Context : DbContext {
        public DbSet<A> As { get; set; }
    }

    class A {
        public int Id { get; set; }
        public B B { get; set; }
    }

    class B {
        public int Id { get; set; }
        public int Foo { get; set; }
    }
}

The output is:

A: ID=1
B: ID=1, Foo=1
A: ID=1
B: null

In this sample code, for some reason when I retrieve A in a new Context, its subproperty B is null. If I set a breakpoint and connect to the database at the point where B is null, everything looks to be in order:

Table: A
--------
Id    B_Id
1     1

Table: B
--------
Id    Foo
1     1

I'm just trying to learn Code First, so I may have a gross misunderstanding here, but this seems very strange to me. Can anyone explain this behavior?

Upvotes: 0

Views: 146

Answers (3)

Diego Mijelshon
Diego Mijelshon

Reputation: 52725

Both answers provided so far are unnecessarily cumbersome.

Just make your entity classes public and declare your navigation properties as virtual, and EF will load them lazily (i.e. on demand)

The DbContext must be open (i.e. not disposed) when you access the navigation property for this to work.

Upvotes: 2

Dennis Traub
Dennis Traub

Reputation: 51634

By default Entity Framework only joins tables (and this is what navigation properties usually mao to, Joins) when explicitly told to do so. You can use the Include() method:

var a = context.As.Include("B").Single();

You can also load properties after loading the entity itself. This is an implementation of the Lazy Loading pattern (which should be handled with care, it can be a real PITA)

var a = context.As.Single();
// some other code
if (!a.BReference.IsLoaded())
    a.BReference.Load();

Upvotes: 0

Kirill Bestemyanov
Kirill Bestemyanov

Reputation: 11964

You need Include them.

You need do something like this:

var aWithNavProperties = As.Where(a=>a.Id==id).Include(a=>a.B).Single();

Upvotes: 0

Related Questions