Reputation: 631
I have this simple model:
class Parent
{
public int Id { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
class Child
{
public int Id { get; set; }
public int ParentId { get; set; }
public virtual Parent Parent { get; set; }
}
class MyContext : DbContext
{
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Child>().HasRequired(s => s.Parent).WithMany(s => s.Children).HasForeignKey(s => s.ParentId);
base.OnModelCreating(modelBuilder);
}
}
And when I use MyContext
as below, I get null reference exception because child.Parent
is null
var context = new MyContext();
var child = context.Children.First();
var parentId = child.Parent.Id; // Parent == null
To solve this problem I have to change the access modifier of Parent
and Child
classes to be public
.
Why is that required ? Or is this just a bug ?
Upvotes: 4
Views: 160
Reputation: 5314
First, to clear something up: your classes aren't private
, they're internal
. You can't declare a top-level type (a non-nested type) to be private (see MSDN Access Modifiers for more info).
Second, Lazy Loading is enabled by default for code first. As octaviocci mentioned, if you're expecting to use Lazy Loading you need to declare them public: it's just part of the requirements. By declaring your Navigation properties as virtual
you're telling EF that you expect to use lazy loading. If you don't want to, you can (should) remove the virtual
keyword. Then, when getting your entities, use the Include
method to eagerly load related entities.
var context = new MyContext();
var child = context.Children.Include(c => c.Parent).First();
var parentId = child.Parent.Id;
Upvotes: 2
Reputation: 39376
That is not a bug, you are using a feature of Entity Framework called Lazy Loading, and to use it you need to meet some requirements that you can find in this link. One of those requirements is that your entity classes must be public
. In that link you will find a proper explanation of why you should meet those requirements, but in summary your issue is because EF can't create a proxy class from your entity, due to that you can't use lazy loading. You already are meeting the main requirement for lazy loading which is your navigation properties must be virtual
, but first you must meet the requirements that EF needs to create a proxy class.
As an additional resource I suggest you look this msdn page where you can find all the ways to load related entities using EF.
Upvotes: 5