Reputation: 6016
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
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
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
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