Migrating from NHibernate to Entity Framework

I’ve been a supporter and user of NHibernate for nearly 10 years. While not part of the original NHibernate Mafia, I’ve long enjoyed NHibernate’s ability to rich, behavioral domain models. I wasn’t happy with the initial designs of Entity Framework, but since it’s been many years since that vote of no confidence thing, I wanted to revisit EF6, especially after the 6.1 release and rich code-first model. For the 99% case, it looked very similar to how I used NHibernate.

NHibernate is still a more mature product, and includes features that it’s had for literally a decade that EF doesn’t have, but for a couple of reasons I wanted to give EF a go on a real project and real domain model that was already using NHibernate successfully. Surprisingly, it only took me a few days to completely make the transition and have all tests pass. So why am I looking to make the switch? Two big reasons:

  • With a couple big committers leaving the project, there’s a void in the leadership and direction of the project
  • Bugs that I’ve run into have been open for years with no fix in sight

A project as large as NHibernate needs a strong OSS community to back it up, or barring that, corporate sponsorship. EF is OSS and has corporate sponsorship.

As  side note, OSS as it currently stands in .NET is only currently successful if the project is small and targeted in scope, or has a company backing it, as seen by reading the tea leaves.

A lot of my opinions on Entity Framework were based on the 5 and 4 releases, so it was time to revisit a lot of my assumptions.

Migrating

In my solution, I was already using the code-based mapping in NHibernate, making the switch in my configuration was relatively straightforward. Additionally, most of my configuration that was originally building up a Configuration class simply moved to my derived DbContext EF class.

Migrating my class mappings and usage was mainly an exercise in regular expressions. One of the reasons why I’m never too worried about switching out infrastructure components who have large feature parity is you find that the differences are mainly API differences, and those are easy to switch out. I don’t like abstracting my ORM, that’s largely a waste of time, and yet it still only took me in a code base of around 60-70 entities about a day to get a compiling solution. I did replacements of:

  • ISession –> DbContext
  • session.QueryOver<T> –> dbContext.Set<T>
  • session.Query<T> –> dbContext.Set<T>
  • Query<T>.Fetch() –> Set<T>.Include()
  • session.CreateSQLQuery –> dbContext.Database.SqlQuery
  • ClassMapping<T> –> EntityTypeConfiguration<T>
  • etc

If you can write decent regular expressions including substitutions, you can perform 90% of the migration just by simple “Find and Replace” across the entire solution. And after 3 days, the entire solution was migrated from NHibernate to EF6.

I did have some problems I ran into. First, one-to-one associations are possible in EF6, but typically require…strange hoops to go through. Things like adding a FK to both tables, or creating combination keys. In NH, a two-way one-to-one association are possible with only one FK. Other things I ran into that don’t exist:

Some of these are possible to work around, some aren’t. Global filters, for example, is very difficult to implement unless you have hooks in the infrastructure. With NHibernate, it was brain-dead simple to implement multi-tenancy with a tenant discriminator column. The good news is that these are all on the EF team’s radar and I didn’t need that specific feature in this codebase.

So why did I ultimately want to make the switch? It came down to a pattern of usage I’ve taken with regards to LINQ and AutoMapper. With NHibernate, anything beyond a very simple projection in LINQ wouldn’t work, but does work in EF. Given a choice of never having to worry about lazy loading problems ever, ever again without resorting to document databases and its baby-with-the-bathwater approach, I’ll go with EF.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Entity Framework, NHibernate. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • ray2k

    I suppose it goes without saying that you’re using Sql Server, right?

    • jbogard

      Is there anything else? ;)

      • ray2k

        Hah, well yeah it is the only db platform I’ve used professionally as well. Just playing devil’s advocate I guess- although I just googled and apparently the mysql .net client supports EF6 so there goes that. Times they are a changin

        • Laurent Nullens

          And what about Oracle :) … Oracle odp.net is always far behind the latest release of EF. Currently you can only use EF5…

          • Arturo Hernandez

            I use Oracle with code first via dotConnect. It’s working fine so far.

        • http://alexeyzimarev.blogspot.com Alexey Zimarev

          SQLite data provider for .NET project also supports EF, which makes it possible to write behaviour tests for the code that uses EF. At least this is not a biggest issue now.

      • http://ubikuity.net Ubikuity

        Rob Conery wrote a post about EF6 with Postgresql:
        http://www.wekeroad.com/2014/02/05/using-entity-framework-6-with-postgresql/
        “This isn’t a production-grade solution because, frankly, it’s slow and SQL Server is built into the bones of Entity Framework”.

  • http://darrenkopp.com/ Darren Kopp

    Entity Framework also doesn’t support components either. EF had complex types, but the rules are different from components, so another thing to possibly look out for.

    • jbogard

      TBH I’ve not had a *ton* of success with components in NHibernate. I always run into problems with nulls etc.

  • http://kevinberridge.com/ Kevin Berridge

    “Given a choice of never having to worry about lazy loading problems ever…” I’d love to hear more details about how exactly you’re using EF to avoid lazy loading! It’s a problem I’ve long struggled with but haven’t found any good solutions for.

  • http://trycatchfail.com/ Matt Honeycutt

    I’ve also made the switch from NHibernate to EF for the exact same reasons you mentioned. EF is not perfect, but neither was NHibernate.

  • mxmissile

    http://stackoverflow.com/questions/4928214/iusertype-usertypeconvention-equivalent-in-entity-framework-code-first

    This is why I have not made the switch. I have a few large projects that depend on this. Looking at EF going forward with new projects however.

  • rippo

    I have now decided my future lies elsewhere than NHibernate, dam shame really but that’s the risk with OSS when the two “big guns” leave. After spending 5 years of my life I feel like I am losing a friend. Albeit a friend that is showing signs of sinking into the depths of history.

    A pity a commercial entity never really backed it and paid the contributors full time.

  • jonas bieberlake

    The one-to-one mapping hoola hoops in EF has always been my major complaint. I’ve recently become more of a fan of micro ORMs though.

  • Michael George

    How do you handle Encapsulated Collections (http://lostechies.com/jimmybogard/2010/03/10/strengthening-your-domain-encapsulated-collections/) in EF with a public IEnumerable property? I’ve spent too much time on this issue lately and just went back to using ICollection.

    • jbogard

      Same, just went back to ICollection with additional specialized methods. All the LINQ support wants ICollection anyway.

  • michael
  • gleb Chermennov

    Of course each situation is different, but on my new job I tried NHibernate for many scenarios – and it’s so much better than EF, I won’t go back ever again.

  • http://blog.waynemolina.com Wayne Molina

    Good article. If anything I’d say a .NET developer should pick up EF at some point anyways since it’s going to be the default in many cases. I’ve actually (well, suspected) lost job interviews because I was on the NHibernate bandwagon and the place I was interviewing at had never heard of it but used plain Linq to Sql or EF because that was the Microsoft solution.

    I use EF a bit at my current job and it’s not that bad; it has some weirdness and IMO it’s still a bit bloated, but it gets the job done and you can do most of the same things.

    • http://alexeyzimarev.blogspot.com Alexey Zimarev

      With current variance of persistence mechanism, I really hope no serious .NET developer would ever consider EF as a “default choice”. Also, would it be wise to work for a company that dumps a candidate that knows one ORM tools and does not know the other just yet? Isn’t something fundamentally wrong with this approach?

      • http://blog.waynemolina.com Wayne Molina

        I would definitely agree that something is wrong with it, but the reality is that’s what can happen.

  • jphamilton

    Doesn’t AsNoTracking essentially give you a read only entity? It turns off change tracking.

    • jbogard

      In NH you can do that globally on a per-entity basis.

  • Mike Cole

    Another benefit of using EF is the tight integration with EF Migrations. There are definitely some disadvantages of EF over NH, but to me EF Migrations always trumped those because it works so well in my environment.

    • jbogard

      yeah, agree. though i use RoundHouse, it’s big missing feature imo

    • http://colinbowern.com Colin Bowern

      FluentMigrator gives me a bit more control over the migration – when it comes to data I prefer a little less magical unicorn and a bit more explicit steps.

      • Mike Cole

        You can customize any EF Migrations step. It simply scaffolds the new step based on the differences it detects in your Model, and it used pretty sensible conventions. After scaffolding, you can do whatever you want to the migration.

        That assumes you’re using code-based migrations instead of automatic migrations, which you should probably be doing anyway on everything outside of a very simple project.

        • http://alexeyzimarev.blogspot.com Alexey Zimarev

          No real difference with Fluent Migrator really. We use a fork of FM.T4 for scaffolding and some other tools, works perfectly fine. And it has nothing to do with ORM.

      • Mike Cole

        Isn’t using an ORM in general a little magical unicorney?

  • Samer Abu Rabie

    Well, I feel like this is a farewell party for our old friend nHibernate :) , damn I love that project and recently I had the chance to work on the EF6 and nHibernate at the same time, I WILL STILL PICK nHibernate :) , EF6 is not bad, but really weird !!! I mean really really weird, alot of things I could achieve in nHibernate just without even thinking about are somehow hard to do in EF6.

    Any how I believe your point is true, nHibernate is in a limbo state currently and its future is unknown, and that is a problem.

  • Dennis Kozora

    EF6 does NOT support simple primative collection types (ie… List). Suggested solutions are to use a string property (mapped to a VARCHAR column) that splits and converts the data into a collection inside the entity.

    Complex key to delete orphans http://stackoverflow.com/questions/10835439/can-ef-automatically-delete-data-that-is-orphaned-where-the-parent-is-not-delet.

    The common practice of an entity with both a FK ID property as well as an object reference to the parent is strange. EF Entity models tend to require leaking more of the EF Framework into the implementation.

    That said, EF6 is an improvement from its earlier versions.The code first and fluent infrastructure is better.

    • jbogard

      I’ve been bitten by the primitive collection types, so I’ve avoided them in NH, personally. Easier just to create an entity. That one’s not a showstopper for me, personally. The delete orphan thing is weird, I wound up overriding SaveChanges and detecting orphans.

  • bdaniel7

    This says a lot about NH vs. EF: https://entityframework.codeplex.com/workitem/864

  • mxmissile

    Jimmy are you wrapping your EF interactions in a using(var db = new DbContext()) block? Or are you injecting your DBContext as a dependency?

    • jbogard

      Injecting, I just replaced my configuration of ISession w/ DbContext, so my controller receive a DbContext instance. I’ll blog about it :)

  • http://six.dev-heaven.net Sickboy

    We just migrated from Linq2Sql to EF Code First and we’ll never look back.
    The migrations are definitely a big thing and the async support is a nice bonus too.

    We were considering NHibernate, in part due to the many great words of respectable people incl you Jimmy :)
    EF won mostly due to being MS supported and hearing good things about EF 6 and code first advances etc.

    Using it together with AutoMapper projections is just bliss :)

  • http://alexeyzimarev.blogspot.com Alexey Zimarev

    EF is missing proper interfaces, schema update and validation and many other important features like HiLo keys that you already mentioned. It is very sad that NH is not getting any backing…

  • Pingback: Danish Developer Conference 2014 – Aftermath « madstt.dk

  • Pingback: Missing NHibernate features in Entity Framework | Jimmy Bogard's Blog

  • Pingback: Some DDD+EF Resources | The Data Farm

  • Tony Henrique

    There is no MySQL / MariaDB support on EF6?

  • Pingback: Trinity Technology Group – Entity Framework 6 vs NHibernate 4: Why EF6 will dominate the .NET ORM space in the near-future