Wednesday, June 17, 2009

Adventures while building a Silverlight Enterprise application part #13

At times you run into decisions made at the early stages of design, that you regret, or at least find inconvenient. This happens to the best of us, especially when using new technologies. In our case we ran into the downside of using ADO.NET Entity Framework (EF) in our application and part #13 already looked like a good one to look at why this is the case.

Why EF doesn't always make sense
Because we are talking a big application here (several hundred forms and grids), and because we are using Silverlight 2 as our client, we decided to make a Business Layer Service, that takes care of our CRUD operations and make this generic. This means we now only have five operations instead of having over a thousand. This still makes us very happy as maintenance is low and you don't have to bother with a lot of code in this part of the system, however...

... in EF, whenever you do a save you need to supply all the connected entities or at least a reference it can use. For a small application with a very limited number of entities this is not a problem. Just code it up for each class and you're done. For our application however, we have a generic save and although we are able to write code for separate business objects (which translate into entities in our service), we'd rather not do this for something that should be the same for all our objects. I should state that this choice was a direct result of us using Silverlight 2 as our client. Writing several hundred save routines sounds like a job for an intern, which we don't have. :-)

We did end up building a generic save, but it did take some hassle to make it work in all scenarios. Especially combining both saving a new entity with saving an already existing one proved to be somewhat problematic.

If I then look further back in the process and see the effort that wend in to building the generic loading in several scenarios, getting a single item, getting a list of items based on some criteria, etc., I'm realy not sure if it was worth the effort with using EF. Why not just build your own?

The good
There is one reason however, and that's the model. The fact that you have in intermittend model that all your code is based on is something that may very well prove very valuable in the future. You could make changes to your datamodel and just change your mappings to go with it and presto, it still works.

If you're reading this and think to yourself: "Design your datamodel right and there is no need to do this", then you realy should get a few more years of experience in the new world. It is no longer acceptable to say that something can't be done, because the datamodel doesn't support it. Customers will not understand / don't care about this and just tell us to fix it and they are right (they eventually pay my salary :-) ).

So was it a bad choice? Should you or shouldn't you use EF in your larger applications? In our case I'd say it hasn't payed itself back yet, but it very well may still do that. I guess it still depends on your application and you should always have a good look at requirements like lifespan, scalability, performance, etc.. In general I think that EF can work for larger applications (as it does work for us), but you shouldn't be caught by what the demos try to make us believe. You can't build your data access services in a matter of minutes, especially if you need your service to work with Silverlight 2. It can still take months to do it with EF.

I hope this post is helpful to you when making your technology choices. Please leave any comments and/or questions below. I'm always happy to read and reply to them.


  1. Is this something that could be solved using a unit of work pattern ?

  2. Hi SteveG, thanks for your intelligent comment.

    In fact we do use the unit of work pattern. What we actually send back to the Business Layer Service is a unit of work. We then persist this in the Business Layer Service by loading the full objects that are impacted by the work (or creating new ones if implicated by the work) and then executing the work on them.