4

This one has me stumped.

I have a Customer and Order entity. the Customer can have many Orders.

Where the Customer has 10,000 orders when I create a new Order and set the Customer property (Order.Customer = customer) there is a LONG delay (20s of seconds). It appears that the context is loading all 10,000 orders before adding this new one.

I am not currently using FKs directly which I suspect may help.

Any ideas how I can improve matters without a massive refactor?

Cheers.

Mark Chidlow
  • 1,432
  • 2
  • 24
  • 43

2 Answers2

9

The problem is most probably that you are using T4 POCO template. This template generates nasty fixup methods and use them internally in all navigation properties. If you modify navigation property on one side it triggers fixup which will try to modify reverse navigation property to make the object graph consistent. And here comes the problem. Once you assign Customer property to the Order instance it will fixup Orders property on the Customer instance but fixup access property as any other code and triggers lazy loading of all customer's orders.

There are only few solutions:

  • Use Foreign key relation ship and set FK property. That should work for inserts but for update it can still cause problems because setting FK property to another value will set null to navigation property and that will again trigger fixup for previous parent.
  • Turn off lazy loading for this operation - you most probably doesn't need it to create new order.
  • Modify template and remove fixupus
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • Thanks Ladislav. I think you are absolutely right (I am using T4 POCOs). When you say 'Turn off lazy loading for this operation - you most probably doesn't need it to create new order', can you please go into this a little further? – Mark Chidlow Jun 16 '11 at 21:37
  • Use something like `context.ContextOptions.LazyLoadingEnabled = false;` You can set this selectively as you need it. Lazy loading allows loading navigation properties when you access them first time. It is sometimes handy but not in this case. – Ladislav Mrnka Jun 16 '11 at 21:50
  • OK I have investigated further and it is certainly the T4 POCO fixup. Would be nice to be able to add an Order without triggering the fix up. I made the initial mistake of not allowing direct access to FK IDs which would solve this issue. I did read though that the code-first (as supported by CTP 5) does not require this fix-up code - will look into this. Anyway thanks for all your help. – Mark Chidlow Jun 18 '11 at 16:08
  • OK how about this. If I remove fixup completely from the T4 template what impact is this likely to have? Yes I appreciate that you don't know what my code/app does but what issues should I look for? Removing fixup for Customer > Orders has no impact but I have performance issues elsewhere for the same reason. – Mark Chidlow Jun 18 '11 at 18:08
  • 1
    You can remove fixups but you must be aware of that in complex business logic. Adding entity to one side of the relation will not correctly modify other side. – Ladislav Mrnka Jun 19 '11 at 12:27
  • Thanks Ladislav. So if I have customer.Orders.Add(new Order{...}) one-to-many, without fixup then I'm not sure what the issue is? Or does this only impact many-to-many? – Mark Chidlow Jun 20 '11 at 08:46
  • In such case `Order` will not have correctly setup `Customer` navigation propety if you don't have fixups. If you expect customer to be set later in your code you will have a problem. – Ladislav Mrnka Jun 20 '11 at 08:59
1

Maybe a different approach might work. When you have a customer instance try:

customer.Orders.Add(new Order(){parameter1 = value1, parameter2=valu2, etc.})

Am not @work right now so don't have any code by hand to check entity structure (work with Self-tracking entities for a project) to see if this makes sense. But by adding it to the collection of Orders the entity might resolve the relation between order and customer without getting all the other 10k orders of this specific customer.

Youp Bernoulli
  • 5,303
  • 5
  • 39
  • 59
  • Thanks Joep. I did try that and I am seeing the same delay. I suspect Ladislav has it spot on. I really dislike those fixup methods! – Mark Chidlow Jun 16 '11 at 21:35
  • Okay. Those fixup methods also have their well intended functionality off-course but may sometimes be annoying. But when using poco's: didin't you already detach them from the context to be send to some client? And when you are within the context why do you need to add some order. This typically seems to be a "client-side" initiated action? – Youp Bernoulli Jun 17 '11 at 05:17