1

I have some code that looks a little like this:

var query = from row in context.Orders.Include("Customer") 
where row.Id = 5 
select row;

var result = query.FirstOrDefault();

if(result == null)
{
    result = new Order {CustomerId=5,...}
    context.Orders.Add(result);
    context.SaveChanges();

    // at this point result.Customer is null
    // and is not lazy-loaded by EF on access
}

return result;

As you can see on above code then if the insert happens then the Customer property of the result is not included, giving me an error later on in my code.

How can I ensure that result.Customer is loaded from the database when result is inserted? Can I do so without manually selecting it?

L-Four
  • 11,965
  • 8
  • 52
  • 103
Thomas Koelle
  • 2,765
  • 2
  • 20
  • 34
  • 2
    "As you can see on above code ... the Customer property of the result is not included" How can we see that? Whats your exact problem with the code? What error messages you see "later in code"? Currently its hard to understand what you are asking for. – BlueM May 07 '14 at 12:11
  • @Iain Galloway thanks for the edit. – BlueM May 07 '14 at 12:29
  • Your query looks odd to me because you are retrieving the `Order` with ID = 5 and if you don't find it you create a new order for `Customer` with ID = 5. Are you sure the query shouldn't be `from cust in context.Customers.Include("Orders") where cust.ID = 5 select cust`? – Colin May 07 '14 at 12:37
  • 1
    Also http://stackoverflow.com/questions/15552891/entity-framework-i-set-the-foreign-key-savechanges-then-access-the-navigation – Iain Galloway May 07 '14 at 12:45

1 Answers1

3

EF can't magic up the Customer object without selecting it. All you have here is an Id. Something will need to go to the database and find the customer object with Id #5.

EF can't lazy load it here because your result is actually a POCO Order and not the EF-generated proxy that knows how to lazy-load.

The easiest thing to do might be to query up the customer and set the relationship up by value instead of (or as well as) by id:-

if(result == null)
{
  result = new Order
  {
    Customer = context.Customers.Single(x => x.Id == 5);
    ...
  };
  context.Orders.Add(result);
  context.SaveChanges();
}

Alternately you can make use of context.Orders.Create() such that you're working with an EF proxy in the first place:-

if(result == null)
{
  var result = context.Orders.Create();
  result.CustomerId = 5;
  ...
}

Beware, though, that depending on the behaviour expected in your domain it's often not a good idea to mix queries and commands up like this. You might want to do some reading around CQRS - e.g. http://cqrs.nu/

The creation of an order is a fairly important operation. Wedging it into a query for an order that doesn't exist yet might come back and bite you in the future.

Iain Galloway
  • 16,882
  • 4
  • 50
  • 73
  • My example was ofcourse simplified to only ask for the basics, and therefore this answer fits my code very well. I will try to implement it, and then my "Customer" query will do all the includes I need. The real code would have perhaps 10 includes to the Customer, and my real scenario have nothing to do with orders etc. but simply made because most can relate to that easily. – Thomas Koelle May 07 '14 at 14:13