Wednesday, January 9, 2013

Entity Framework -Revisited

I'm starting a new project soon for a new client and I've finally had some time to do some prep work to set up the skeleton of the solution/projects as well as investigate some "new" technologies. One of the things that I've revisited is Entity Framework(EF). I thought a great way to get my blogging going again was to post my thoughts on EF.

<gasp>Turns out is not as bad as I thought it was...</gasp>

Why I hate(d) Entity Framework:

Until 4 weeks ago, I was not a fan of EF. This hate of EF was born out of early adoption of the technology (V1.1) and attempting to implement this in an N-Tier Application. The pain points were many and there were numerous times when we almost put the project on hold for a week while we ripped out all Entity Framework pumping and re-laid L2SQL  Each time the pain of doing so seemed to out weight the benefits and then 2 days later we would uncover something ELSE that would make EF seem even worse. This would then force us to revisit the EF vs. L2SQL thing again with the same resolution.

Note: I will allow that we were all moving really quickly in the project and that none of us really understood EF to the level that we all should have, but the idea of the ORM in general is to make the lives of developers easier. (If it can't do that, then there is no reason to use a technology IMO). However, if we had known how it really worked, we probably would not have used it, so........

Here are 2 of the many reasons why it was hard to use:

 

Reason 1:

If you just wanted to update the foreign key on a row to a different foreign key, you had to use EF to pull that item out of the Database and then assign that item to the navigation property. So if an address table had a foreign key to the state table (StateId), you couldn't just update the value in the StateId column to the proper state, you had to set the Address.State object and then save changes.

Reason 2:

There was a large amount of work/tracking that the code (and hence the developer) had to do to track the various states of the objects through the life cycle. Essentially pulling data out of the database was nice and easy, but inserting or updating data was a nightmare. We would end up with duplicate entries in the database, or exceptions thrown by the EF context for primary key constraints as the context would attempt to insert an object instead of updating an existing item.

There are many more reasons, but for the sake of sanity, I've repressed those into the dark recesses of my mind which I hope never again see the light of day.

How much did I really hate it?

It was so difficult that eventually we stopped any new development with EF and created a L2SQL context that we started using from that point with any new code. While it would seem like managing two ORM instances would be a pain, EF was so immature that it seemed less painful to us.


Additionally, On the 2 subsequent projects I've been on, we've exclusively used L2SQL, even though there hasn't been any new Features or developments in that technology for a while, and is for the most part considered Dead. It did what we needed it to do, and kept simple things simple. What else can you ask for?

2nd chance?

I've been to a few conferences and MSFT events over the past couple of years that piqued my interest in the newer versions, but my previous experiences prevented me from actually looking into it as a viable ORM for future projects. It still didn't have the feel of an enterprise solution, especially when all I would see mentioned in the talks  would be the code first approach. While the code first approach is "cool" IMO I its not something an enterprise app could/would use, much like RIA services for Silverlight. Potentially useful in small rapid application development scenarios, but not much elsewhere

However, I decided to take another look and I was pleasantly surprised. Here are the things I'm finding super useful:
DBContext object
The introduction of the DBContext object makes working with objects much easier. It abstracts away most of the dirty work of attaching/detaching and monitoring objects that are going in and out of the database. There is a lot of information about there about this that I wont reproduce here, but it simplifies working with the database context and the object graph much easier.
If you need more functionality than what is exposed in the DBContext object, you can still use the object context for more operations that are closer to the metal.
If you are able to accomplish all of your work with the DBContext, upgrading to a newer version of EF is supposed to be pain free as the DBContext object is "guaranteed" to be supported in future versions of EF
Object Inheritance:
Entity Framework now supports multiple types of Entity structures(Table Per type, Table per Hierarchy, and Table per Concrete Type). For us this is going to be immensely helpful. We're working off of an existing database, that has tables that contain data for multiple types of entities so by setting up inheritance in the model we can use built in EF functionality to extract just the types we need.

Example: We have a large "Contact" table that has Vendors, Companies, People etc. We simply create a "Person" entity and base it off of the type field on the database. (Great explanation here)

While the idea of inheritance isn’t brand spanking new to EF, its something we never took advantage of before and I have to say I’m super excited about it.

Enforcement of Non-existent relationships
As mentioned, we're working with an existing database. Unfortunately, the people who created the database didn't believe in using  relationships to enforce data integrity. While this has the "nice" side effect of making data cleansing easy by being able to delete almost any row out of any table, it destroys the massive benefit of navigation properties in the ORM. Entity Framework allows you to add the relationships directly into the model. This allows the code to enforce the relationship, even though the database does not.
Simply open the design surface, select Relationship and drag the relationship between the entities. The properties of the relationship can be modified to match you specific scenario (Multiplicity, name, etc.)

Creation of a generic EF Repository Class
While this might not be something that everyone needs (or even endorses) Entity Framework does allow you to create a simple Repository Class that can be used for all entities in the model. The use of DBContext.Set() allows you to create a repository class of type TEntity and do all manner of operations generically, thus reducing the amount of code needed for a simple repository (Context name blurred to protect the innocent)


Cross your fingers!

I hoping that since I've done more investigation into EF this time and understand it a bit better, that we'll be more successful using it and hopefully reap the benefits of the good work of the folks on the Entity Framework team. I'll post more later as a follow up to let everyone know how it went!

No comments:

Post a Comment