Question

I've seen this question asked a few times but nothing solves my problem. I've created the most simple version I can:

public class Order
{
    public int OrderId { get; set; }
    public virtual List<Item> Items { get; set; } //One to many navigation property
}

public class Item
{
    public int ItemId { get; set; }
    public string Description { get; set; }
}

An order can have many items. Simple. Now to interact with the EF:

using (var context = new TestContext())
{
    Order test = new Order();
    context.Orders.Add(test);
    context.SaveChanges();
    test.Items.Add(new Item {Description = "test"});  // no good - test.Items is null!
}

If I do this test.Items will be null and I cannot interact with it. However if I "refresh" the context all is well:

using (var context = new TestContext())
{
    context.Orders.Add(new Order());
    context.SaveChanges();
}

using (var context = new TestContext())
{
    Order test = context.Orders.First();
    test.Items.Add(new Item {Description = "test"});  // Happy days - test.Items is NOT null :)
}

What am I missing? Or do I really need to get a fresh context every time I add an item with a one to many navigation property?

Thanks in advance, oh wise guru of ether that know-eth the truth on this subject!

Was it helpful?

Solution

You need to create your entities using DbSet.Create() when using proxy entities (the default setting).

Entity Framework Code First will create new classes at runtime that inherit from your model classes. So you're not working with your Order class, but one that inherits from it. This new implementation will override your virtual navigation properties to implement additional features (such as lazy loading).

The specific feature you require here is to notice when the collection has changed. Your class does not provide any features like this (and should not), but the proxy class does.

Now when you new Class() your model object, it will be exactly your object. It won't be the proxy entity and therefor won't have the additional features. DbSet.Create() on the other hand will return the proxy entity, upcasted to your class, so you're working with the proxy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top