2

I'm working on a personal project using WPF with Entity Framework and Self Tracking Entities. I have a WCF web service which exposes some methods for the CRUD operations. Today I decided to do some tests and to see what actually travels over this service and even though I expected something like this, I got really disappointed. The problem is that for a simple update (or delete) operation for just one object - lets say Category I send to the server the whole object graph, including all of its parent categories, their items, child categories and their items, etc. I my case it was a 170 KB xml file on a really small database (2 main categories and about 20 total and about 60 items). I can't imagine what will happen if I have a really big database.

I tried to google for some articles concerning traffic optimization with STE, but with no success, so I decided to ask here if somebody has done something similar, knows some good practices, etc.

One of the possible ways I came out with is to get the data I need per object with more service calls:

return context.Categories.ToList();//only the categories
...
return context.Items.ToList();//only the items

Instead of:

return context.Categories.Include("Items").ToList();

This way the categories and the items will be separated and when making changes or deleting some objects the data sent over the wire will be less.

Has any of you faced a similar problem and how did you solve it or did you solve it?

Ivan Nikolov
  • 793
  • 4
  • 15
  • One reason why not to use self tracking entities. I think it has some overhead because the origninal values are probably transmitted over the wire too. – yonexbat Jun 21 '11 at 05:54
  • Yes, they are. I also think that in terms of optimization and creating serious applications it's much better to use just ADO.NET or other technologies where you don't have to send megabytes of data only to change a single letter, no matter the other good things Entity Framework provides you. They are just not enough for me (and probably not only me) to close my eyes. – Ivan Nikolov Jun 21 '11 at 08:50

2 Answers2

1

We've encountered similiar challenges. First of all, as you already mentioned, is to keep the entities as small as possible (as dictated by the desired client functionality). And second, when sending entities back over the wire to be persisted: strip all navigation properties (nested objects) when they haven't changed. This sounds very simple but is not at all trivial. What we do is to recursively dig into the entities present in trackable collections of say the "topmost" entity (and their trackable collections, and theirs, and...) and remove them when their ChangeTracking state is "Unchanged". But be carefull with this, because in some cases you still need these entities because they have been removed or added to trackable collections of their parent entity (so then you shouldn't remove them).

This, what we call "StripEntity", is also mentioned (not with any code sample or whatsoever) in Julie Lerman's - Programming Entity Framework.

And although it might not be as efficient as a more purist kind of approach, the use of STE's saves a lot of code for queries against the database. We are not in need for optimal performance in a high traffic situation, so STE's suit our needs and takes away a lot of code to communicate with the database. You have to decide for your situation what the "best" solution is. Good luck!

Youp Bernoulli
  • 5,303
  • 5
  • 39
  • 59
1

You can find an Entity Framework project item at http://selftrackingentity.codeplex.com/. With version 0.9.8, I added a method called GetObjectGraphChanges() that returns an optimized entity object graph with only objects that have changes.

Also, there are two helper methods: EstimateObjectGraphSize() and EstimateObjectGraphChangeSize(). The first method returns the estimate size of the whole entity object along with its object graph; and the later returns the estimate size of the optimized entity object graph with only object that have changes. With these two helper methods, you can decide whether it makes sense to call GetObjectGraphChanges() or not.

EdChum
  • 376,765
  • 198
  • 813
  • 562
Weidong Shen
  • 69
  • 1
  • 2