Why I still don't use Entity Framework for small-to-medium business applications


This post is really about the cons of Entity Framework. I know, I know, it's sacrilege to not be in love with EF and using it everywhere, and I feel I am taking some professional risk expressing these thoughts. But I actually find Entity Framework to be problematic in many ways, both technologically and philosophically, and I am frustrated that it is now the "standard" way to do data access in Microsoft land. To be the standard implies "generally suitable for most applications", which in my experience, Entity Framework is not.


You can say "no one's forcing you to use it, use whatever you want", but this is the "standard" that gets all the press, abundant training materials, and all the new tooling improvements. If I want that condition to change, or want to also see more investment elsewhere, I have to express thoughtful dissonance publicly.

It should be noted that my perspective is one of a Development Manager with some hands-on experience with LINQ (good and bad) but where most of my experience with EF is reviewing work from developers on my team when we tried to adopt EF as a standard. (One of our newer team members has been using it for several years.) I've also watched many videos over the last several months, and got to hear Julie Lerman talk live (yay!) about EF 7 (now EF Core).

First, let's be positive and consider where Entity Framework is meant to be helpful. Let's look at some favorable expert opinions.

Shayam Pather back in 2010 presented this excellent demo of Entity Framework 4. I will say this is a really great video and highly recommended viewing, even if a bit dated.
https://channel9.msdn.com/Events/TechEd/NorthAmerica/2010/DEV324

In it he does a great job reviewing the history of data access at Microsoft, and then makes the following argument for Entity Framework:

  • Data Access technologies evolve (specifically, Microsoft has changed their Data Access strategy at a pretty regular clip).
  • Therefore you should be designing MVC style apps, and putting your Data Access behind a layer of Business Objects, so that when the technology changes you can just swap out the Data Access without affecting the rest of the app. He has an excellent demo of doing this, starting with a simple two-tiered spaghetti code app and doing several refactorings.
  • Furthermore, you should start adopting Entity Framework - this is where Microsoft is investing, and they believe it will suit 80-90% of most applications. 
  • Entity Framework saves you time by eliminating a lot of the looping you have to do with raw ADO.Net; it understands that you want a collection of objects from storage and so just returns a collection; it understands there are child collections, and automatically makes those easily accessible. This is awesome sauce and you are going to love it.

Alrighty. On to the next expert. Dino Esposito wants to convince us T-SQL lovers the EF can be our friend: http://sqlmag.com/entity-framework/5-reasons-why-entity-framework-can-be-your-best-friend

In that article, He lists "5" reasons, but really it seems to boil down to 2 reasons:
  • EF writes better SQL than you do, in a slightly simpler syntax (LINQ).
  • EF encourages you to rise above basic "CRUD" thinking and embrace object-oriented programming in a more conceptual way, and therefore makes you a better programmer.


In addition to these opinions, I would add that with LINQ-to-Entities syntax you are now "database agnostic" to some extent, which often gets air time - "why should I have to be bothered about the persistence layer?"

Now let me state firmly why I consider none of these features to be convincing benefits for me personally.
  • Better separation of concerns? "Now your objects don't have to think about persistence!"
    • Except in the real world, this often isn't how it works. Not everyone is doing MVC. People are often just swapping out ADO.Net calls in their code behind for DBContext calls (rather than talking to an object layer), or are using Entity Data Source controls instead of SQL Data Source controls.
    • Also I think there are other ways to keep your code modular and organized. MVC is not the only answer, and in many cases depending on team size and available skills, not the best answer. Shockingly the "Page Controller" pattern used by WebForms is still very viable (even if you are opposed to using actual WebForms controls) and can be set on top of a set of data services in a web farm if you need to hyper-scale.
  • Preparing for Data Access Evolution?
    • Okay, now let's get a taste of that concept: you need to take your application and charge your client to hyper-architect it, just in case Microsoft changes their DATA ACCESS approach. Note that in this case, YOUR APPLICATION logic hasn't changed, YOUR DATABASE schema hasn't changed, but something about how your application is glued to your database could be changed, so you know, you want to be able to swap that out. Really? Can we say premature optimization?
    • And frankly I just find this whole "rethinking Data Access" every so often to be huge waste of time. We all have plenty to keep up with just mastering new user interface technologies and security practices. How we run our queries and get results back is not something we should have to rethink every three years.
  • Simpler query syntax - LINQ?
    • This is the old "what you're familiar with" problem. I assure you LINQ is plenty confusing to the uninitiated.
    • The LINQ syntax has a couple of major flavors (fluent syntax vs. method syntax), so when someone says they know LINQ, you have to ask additional questions to know if they can use LINQ the way you do. Or you have to train everybody on all available flavors.
    • The LINQ syntax changes depending on which O/RM you are using. So the argument must be "You should learn the EF flavor of LINQ".
    • With T-SQL, you're also using a flavor of SQL that has been extended to work with SQL Server, so it is also "specialized" to some degree - but I would argue that T-SQL is a stronger standard than LINQ, as in, when someone says they are a T-SQL expert, I know exactly what to expect from them.
  • Encourages Object Oriented Design?
    • Okay, I'm going to pull back the curtain here and reveal that my approach to business applications could be thought of as "glorified Access programming on the Web" (yet still scalable to thousands of concurrent users). The fact is that a large swath of small-to-medium business applications are just forms-over-data + reports on schemas with less than 50 tables. These type of applications do require some separation of concerns to be maintainable, but they do not require a beefy object layer. OOP is useful if you are writing a game, or building a code editor, or working on a giant ERP system. But for many many many applications, binding a grid to stored procedures is faster, cheaper, and totally adequate.
  • Database Agnosticism?
    • There are very very few use cases for where "database agnosticism" should be high on your list of "things to architect around". If you are writing a database platform agnostic app, you are writing a very expensive app, and probably one that doesn't perform a tenth as well as it could if you would fully leverage your database platform.
Other things I don't like about Entity Framework and O/RM's in general:

  • Yet another abstraction layer that my team has to Master

    • I don't know anyone that says Entity Framework is an "easy lift". Yes the initial wizards are easy, but ultimately I've mostly heard "it has a learning curve but it's great afterwards". So the question is, does this particular learning curve provide as much value as other learning curves my team could be tackling?
    • O/RM's in general are egregiously "leaky" abstractions. That is, despite their best efforts, the nuances of each database platform ultimately break through, and you end up having to do "special" things to make it work for your chosen platform. (See http://www.joelonsoftware.com/articles/LeakyAbstractions.html for Joel's original treatise on this concept.)
    • There are a lot of nuances regarding when to use certain features. In this very recent video on EF Core, EF Expert Julie Lerman discusses with a couple of other devs where Lazy Loading, which is almost universally encouraged in EF apps, actually doesn't make much sense in Web Applications: https://channel9.msdn.com/Series/aspnetmonsters/ASPNET-Monsters-Episode-47-Julie-Lerman-and-the-State-of-EF-Core?ocid=player 
    • A quote from this video: "That points out that fact though that using an O/RM doesn't divorce you from the need to still understand what's going on in SQL Server", to which Julie responds "profile, profile, profile". So if we think in terms of critical path, which skill is more important, learning EF or learning SQL Profiler? To my dismay, most of the developers I meet have no idea how to use SQL Profiler, even though it's one of the more powerful tools to have in your toolbox in terms of debugging and tuning your applications. We can only master so many things, and I'm not convinced EF should be very high on that list.
    • By the way, Lazy Loading is unavailable in EF Core (EF 7). So all the ASP.Net Core developers are about to get to retrain their minds again on how to structure their data access.
  • Yet another place for things to go wrong

    • Have you ever tried using LINQ to sort a column that contained NULL values? You had to learn a new "workaround" that day, didn't you? Cheap shot: we don't have this problem in T-SQL.
  • Yet another place the Domain Model has to be maintained when it changes (like adding a column).

    • I update my database and test it, and then I also update my EF model and test it. I don't like this duplication of effort, and having to maintain and nurture a "second copy" of the model.
  • Sometimes Stored Procedures make for a more flexible Abstraction Layer.

    • Some things that are amazingly simple to change with a Stored Procedure abstraction layer, like the implementation of Soft Deletes. In my standard approach if I wanted to switch to Soft Delete, I could simply modify my "usp_Noun_Delete" proc to update an "isDeleted" column. No User Interface changes or other middle tier changes required. In Entity Framework however, Soft Deletes require a level 400 session and expert understanding of EF internals. (TechEd 2014 EF 6 presentation: https://www.youtube.com/watch?v=vspEYmp6zWc)
    • O/RM's hard-code the "domain" definitions into the Code, making the code less Flexible. Consider a LINQ query which references a custom table that is needed just for a particular customer instance of a project: MyDBContext.CustomOneOffTable.GetAll() or something similar. Now "CustomOneOffTable" is hard-coded in the solution. In a stored proc world I can use dynamic SQL or simply change the query within one of our standard procs, without having to recompile a bunch of code.
  • The above objection is also known as "O/RM's assume you have a Static Domain Model".

    • However in my world, we build various products that do similar things, but not at all the same things, yet we still want to reuse concepts where we can. A recent example is where we built a new product that needed to reuse our Scheduling module, but we needed it to integrate with an entirely new Messaging module. Happily this only required a single change to a single stored proc and a couple of foreign keys.
    • In this example, I can hear the OOP designers saying "Encapsulate! Encapsulate!" and design a generic higher order object. But in the world of shipping profitable software and keeping complexity at manageable levels, the added complexity of the "super model" is just too much weight and is often not commercially viable.
    • This comment on commercial viability gets at the heart of my complaint about Entity Framework; it assumes that MOST projects in the world need a rich object layer, an inflexible Domain super-model, and that therefore a nice O/RM. In my 17 years of experience shipping software that actually makes money and is commercially viable, there are a LOT of projects that do NOT need this. I've worked on enterprise class projects where having good web services architecture that could scale was MUCH more important than having a good Object Library. We just passed datasets around and the project was still a smashing success - amazing!
  • Reporting, aka, you still need to know your SQL

    • Almost every application requires some reporting. At the point it's time to write reports, you suddenly need to be at least decent with T-SQL and stored procedures to write well performing reports, and you need to have a very solid Database Schema understanding of your Domain. So throw out all that LINQ syntax and your "simplified" object model which helped hide all the Joins in the background - suddenly you need to understand very well what the linking tables are (which don't appear in the EF designer) and how to do the joins.
At the end of the day, I'm still just not a fan of O/RM's. I guess it's the old VB developer in me, but I still agree with Ted Neward's famous opinion on the matter (http://blogs.tedneward.com/post/the-vietnam-of-computer-science/), an opinion that 10 years after being published is still resonating with many devs today.

So in closing, I think Entity Framework is a niche product, good in some places but not anywhere close to being good in all. I think it's a good fit in the following scenario:
  • You have a domain that once established is not expected to flex much. (This is often reasonable, though not always.)
  • Your application is complicated enough to benefit from a rich middle tier - specifically that building a rich middle tier will definitely save your client money in the very first release of the product. Or you are investing in a giant product where the same object (like Invoice) will be used in dozens of places and only OOP can keep the code organized and behavior consistent.
  • You have a large team with separate people specializing in UI, Middle Tier, and Reporting.
Otherwise, I would say you are spending a lot of time learning the nuances of an O/RM when you should be mastering other skills, and finding ways to charge your clients less instead of more. I'll say it again:

How we run our queries and get results back is not something we should have to rethink every three years.

Comments

Popular posts from this blog

SQL 2005 SP4 and MSreplication_subscriptions

Hiding an ASPXGridView Delete button with HTMLRowCreated vs. CommandButtonInitialize

SQL Server Deadlocks - Easy Quick Start Guide