My last post was a bit of a joke and I should explain why after only a few hours of playing with EF that I think it is a horrible technology. Some might say that a few hours is not enough time to completely write off a technology but I have to disagree. I spent a few hours with nHibernate and loved it. a few hours with EF and I wanted to start drinking.
First the good things about it:
- It is integrated into Visual Studio so the whole team is already able to start using it
- You can generate entities off an existing database which is convenient
- The generated items include rules about nullability, type, length, etc.
- You have MS behind it for support (<sarcasm> yippie! </sarcasm>)
- It is quick to get up and running on it
- It would appear to have first class support for mapping to stored procs (I did not try it though as I am not a fan of stored procs for the most part)
- The entities track changes made to them so that when you save you don’t have to worry about missing inserting/updating/deleting a record
Now that I have that out of the way. The bad things:
I tried to look for good things in the EF. I really did but it became obvious to me after 10 minutes that this was not the tool for me. The whole underlying idea is wrong in my opinion. The Entity Framework is really a way to bring your database up into your code (does this remind anyone of datasets?) which is 100% wrong. The database is simply a place to store the state of your business, that is all. It is up to code to define that business, it’s rules, and to persist the data between sessions/reboots/upgrades. This datacentric model that MS seems to constantly promote seems to be like saying that you should build a grocery store based on the dimensions of the shopping cart which is a totally backwards idea (but our industry has no shortage of those).
The designer is flashy and terrible. It initially impressed me that I had my model laid out infront of me but then realized that this is unnecessary, the concept of having a visual designer seems silly to me for this kind of task. For one I am a big keyboard user, if I can’t do something with a keyboard then it is not worth doing and the EF designer is mouse centric. I found it also to not be intuitive. I spent a lot of time hunting around trying to do things but it took me so long to just find/do simple things. Also if you have a database with more than a few tables you can not easily locate a table on the designer. Not being able to quickly find and change a mapping is the biggest killer for me in terms of usability. I found that anything beyond the very simplistic I had to open up the model with an xml editor and do it there which made the designer feel useless.
The framework is so not ready for the real world yet. I generated a model of an existing database and then deleted some of the tables/entities that were not required for my application. This resulted in foreign key issues in the model as it could no longer relate to that table which I could not resolve through the designer. Eventually I had to go into the raw xml of the model and delete the constraint from there. I also tried the update model functionality to re-add these tables but apparently it felt that there was nothing different between the model and the database but generated a bunch of new crap that caused more compile errors so I ended up deleting the whole model and starting over.
The framework generates some nasty looking objects for us that are not persistence ignorant. The “business” objects that the framework generates are highly coupled to the database when they are supposed to be highly coupled to OUR BUSINESS! They are implemented as partial classes so you can add business rules onto them but most developers find partial classes reduce the readability and discoverability of what is happening where in code. This leads to rules that should be in the business objects being placed elsewhere leading to architecture/reusability/consistency issues.
The amount of code that is generated is huge too. For my sample application I have 60 tables which resulted in 18,000 lines of code which is about 300 lines of code per table. In our application that uses this same database and fluent nHibernate it averages out to 24 lines per class (granted the EF is doing lots of work to track changes for us though). I found that this additional code slowed down my build more than I considered acceptable.
The lazy loading story is a complete joke. In other OR/Ms you can have child objects load from the database only when they are accessed which could save a lot of unnecessary database calls or loading logic (i.e. we can take a customer object and just go customer.Orders in our code and behind the scenes the OR/M will load the customers orders at that moment in time). In the entity framework they have deferred loading (deferred in that they will do a better job later). Using EF if you went customer.Orders you would get a null back, what you were supposed to do is go customer.Orders.Load() and then make a call to customer.Orders. This just floored me. The idea of lazy loading has been around for many many years and is simple to implement. One of the biggest issues with the EF implementation is that your business code now has to check if a collection is null and then call load on it when the business code should not care at all about state. If my code saw that customer.Orders was null it would say to me that the customer has no orders. Calling customer.Orders.Load makes zero sense to business code.
I also found it clunky to work with in code and found some unexpected results. For example calling model.Permits.Count returns me how many permits are in our database but model.Permits(0).PermitNumber throws an exception. I also found that you would explicitly have to call save changes all the time which was easy to forget:
Dim model as New Model
Dim permit As New Permit
permit.PermitNumber = 100
permit.Discipline = “B”
model.AddToPermit(permit) <-add it to the Permit table
model.SaveChanges() <-commit the change
model.DeleteObject(permit) <-delete
model.SaveChanges() <-commit the change
I find always having this unit of work idea a bit of a pain myself, especially on a simple application. In more complicated persistence scenarios it could be a nice feature though.
Another issue I had was there was no way to globally write out all the SQL that was being executed to a console/debug stream. You could to see what one query is going to do by running query.ToTraceString() but I could not find a global flag to turn this on. I have found with using other frameworks that have this feature has led me to discover lots of issues when running unit tests and seeing some of the unexpected SQL that is being generated.
Another interesting issue is source control and the EF. EF generates one big class file and one big XML file for the model. If you have a team of more than one person chances are that multiple people will be working on the model at the same time which is going to inevitably lead to a locking/merging nightmare. Having many small files reduces this problem.
The thing that really bugs me about this product is the apparent attitude of the team behind it. There are many good evolved OR/M tools out there already and it feels like they looked at none of them. The team has also apparently not taken any of the community feedback from the betas (or a very very small amount of it) and incorporated it in. My outside impression of the EF team is that they are disconnected from the real world, the community, and the competition to their framework.
The thing that stopped me from looking at EF any further was the refactoring support. I am a big big resharper user and it does not play with EF. I renamed one property of an object generated by EF and everything compiled just fine. When I ran the application and tried to save/load the entity I got the lovely error of “The Member ‘Location’ in the conceptual model type ‘Model.Permit’ is not present in the OSpace type ‘EntityFramework.Stub.Permit’”. Refactoring is a fact of development now days and for EF to fail on a simple rename like this ruled it out for me.
Designing a domain driven application gives us limitless possibilities in how we can express a business and its rules. The application and the database are not a homogenous system, they each have their own roles. A database is just a bucket we store the state of things in. The entity framework makes it feel like my application has to adapt to that bucket so therefore my business is a bucket which in turn makes my application work like a bucket and most clients don’t want a bucket application. The fact that there even is an Entity Framework Vote Of No Confidence that hundreds of developers have signed is good evidence that this product missed the mark and will continue to unless they make some massive changes. Overall I found the EF to be overly complex, frustrating, and not nearly flexible enough for me and I will avoid it at all costs on future projects.
Nice review! Sounds like a make-work project for both MS and their devoted customers.
Excellent review. I haven’t used the framework myself but this is consistent with everything I’ve read so far.
Is this a standard ‘release one’ from Microsoft? Stay tuned for the next release?
In my opinion EF is fundamentally flawed. I find that other mappers (like nHibernate) give me the flexibility to do almost anything I want where as it feels that EF constrains me to follow its idea of how mapping should be done. I know there are some improvements in v2 but I still would pick a tool like NHibernate over it any day.
have anyone used on nHibernate with asp.net 3.5. please let me know as im looking for a reference architecture to use as a baseline in my new application.
Having use EF for nearly a year in a silverlight app, I am happy with the product. I have found very passionate people on my team (who have not used it) to be very opinionated regarding any ORM that they are not familiar with. MS has announced continued support for EF which has encouraged me to use it on my next project too. I have not looked extensively at NHibernate, so I will not comment on it. However, EF works very well in both synchronous and asynchronous modes. The learning curve is steep, but the rewards are great.
One technique you can consider is creating a pseudo tier through the use of partial classes/methods that morror you ORM classes. This technique, although simple can help on several fronts you describe above such as source control. We have developers interacting with DB design in real time with out stepping on toes. The partial classes and methods keeps the human generated code separated from the EF code. BTW, the EF works very well with TFS.
I read your article through and can only give you the solice that my opinion differs dramatically from yours, having used the product so much. I cannot get away from the learning curve problem, which ultimately will deter others from taking the product for the serious extension that it is. However, I find using it today both easy and elegant. It is simple to create functionality and several tiers using EF. I would love for people who have used the product to compare it with other products they have used.
I suppose my investment in learning the EF may also taint my opinion, but I have not found anything it cannot do well.
I concede your point on the refactoring but only advise a layer to insulate you from it. Not very hard to map the EF to a middle tier IMHO. I am not sure if the ‘.Net for RIA Services’ will help in this regard but have found the tier solution to work just fine.
Best of luck in your pursuit of ORM frameworks.
EF User,
I am glad you are happy with the product. The thing that concerns me about your comment is that you have not tried other ORMs and experience how much easier EF alternatives can be. Why should you have to create a pseudo tier to work with a technology? Why not use a technology that works without the additional work?
I have tried EF, nHibernate, and written my own ORM. I found the friction with EF was way to high for me to even consider using it on a production application when I know I could use nHibernate with greater ease. One may argue that nHibernate has a smaller learning curve but I think that EF is (currently) a failed technology that misses the simple goal of being able to easily map objects to a data structure.
Off the top of my head, I have a list of things it can not do well:
1. Separate the domain model from the data model
2. Lazy Loading
3. Add business logic to an object without a partial class (partial classes hurt code readability in most peoples opinion)
4. Refactor
5. Easily navigate to an entity to change something in the designer.
6. Easily work on a large "entity model" i.e. anything over 50 entities (the designer becomes huge and unmanageable)
I am glad you are using EF successfully but I think you should look at other technologies too so that you know the pros and cons of each which will help make the best choice on future projects.
Good review on the EF. At this point EF is just not ready and it is not an ORM. Just another way to bring DB schema to the business tier. I read about good things in VS 2010 (we will wait until then).
But partial classes are very useful. Code readability is an issue only if the class that is written is partial. Nobody is *required* to write partial classes. It is a mere way to extend generated code and that makes it a lot more maintainable and readable. If you are talking about a world with no code generation – absolutely agree that there shouldnt be support for partial class.
I am light years behind chipping away at the digital version of your past ‘Asp.net Unleashed’ What other titles are included in your ‘Unleashed’ series of .net Framework masterpieces? Pls advise
thanks
Strangely, it has gone away again now, but it was basically a neat Javascript VM that allowed you to plant really powerful apps inside Windows windows – app windows, browser windows… It was like the JavaVM, only Javascript and it ran in any context. It was very cool.
I think that last comment from Danny summs it quite well. The most common way to look at the Entity Framework is serving up object instances from a conceptual model. In fact thats the Object Service layer than handles that part. The Object Service layer implements the Identity Map/Unit of Work pattern and it works against the conceptual model.
dave have you looked at the latest release?
Dave, I repeat the above comment. Did you get a chance to look at EF v2? I am currently evaluating EF for a med-big size impl and most of the reviews I see are negative and based on v1. I would love to see your take on v2 too.
TIA,
Shankar
I have not looked at v2 but I have heard it is moving in a better direction but is still not there yet.
its better than V1, hopefully will be more better sooner or later.
The more you fight something, the more anxious you become —the more you’re involved in a bad pattern, the more difficult it is to escape.
I wanted to thank you for this excellent read!! I definitely loved every little bit of it. I have you bookmarked your web site to check out the latest stuff you post.
Wonderful post! I like your blog, and am a regular follower. I will be back monday!
I’m going to subscribe to this blog because it’s very interesting
Thanks for sharing this useful information! Hope that you will continue with the kind of stuff you are doing
Any opinion on this in VS2010 or VS2011 Beta?
I have not looked at it lately myself. I hear it is improved but nHibernate still has way more features over it.