I like to write blog posts where I offer some pragmatic advice. In most posts I try to include tons of code samples and example projects...but this post is different. I am trying to get my head around something so I want to share what is in my head so I can get a conversation started with my readers to help me out. Once you read this post, please comment...
The other day I was responding to a tweet from Doug Purdy. He had posted a link to some new EF 4.0 features by the boss at Microsoft's DevDiv. I, as usual, complained instead of lauded the list. I started a conversation about lazy loading and the potential danger of it, but quickly Doug mentioned that ORM's maybe were the wrong approach in general. That got me thinking (not always a good idea).
Those of you who have followed me for a long time are apt to remember that I go back to ADO (actually even farther back) to a time when writing your own data access layer was the norm. And using that data access layer against your business objects was what we all did.
Things are really different today as most of us now use an Object Relational Mapper (ORM) of one sort or another. Entity Framework, LINQ to SQL, nHibernate, LLBGenPro, etc. They all essentially do the same thing (but in very different ways). The problem is that to some it feels like ORMs are business objects. In fact, ORMs are just data access. Are they making our jobs easier? It depends...
Most ORMs lean heavily on code generation to create entities and other code. The mapping is generally trying to take some relational model and create an object oriented model. It works this way because this is what we've done for a couple of decades. But is it helpful? Perhaps not. But because we build class-based (or object oriented) software today that seems plausable to do.
Object orientation is at a cross-roads in many ways. We've been told for a couple of decades now that it is the way that you can benefit from reuse, ease of development and modeling. Of course, like all magic pills, applying it to every problem space doesn't help. In the case of ORM's, its always felt like we were putting a round peg into a square box.
Don't get me wrong, mapping a rectagular result (e.g. SELECT * FROM Foo) makes a lot of sense. But the problem is that the mapping happens between *related* entities which is hard. Relationships in data stores are not as simple as 1..n, 1..1, or 0..1. By shaping the relational model into a class structure, we're losing fidelity. You can see if you're losing fidelity when an ORM is going to allow you to get deep inside to hint at the actual queries. At that point we're fighting the tools.
I am not anti-ORM at all and I can clearly see how ORMs help build smaller projects easier. This is especially true if your relational model looks like the object model (or as is common in DDD, using the class model to push down the schema). Great if you're building small projects, but when those same techniques are used on large or enterprise solutions, the stack gets big fast (see right). The problem is that we end up with in-memory classes that represent entities, then we need business objects that apply business rules, then DTOs to communicate the shape of hte data across the wire and in some cases data contract classes outside the firewall. Under the ORM entity objects, the ADO.NET managed providers still exist and sometimes an unmanaged stack too. Sometimes that a lot of code to worry about.
My big worry here is that ORMs are seductive. When you start a project and build a data layer with a couple of clicks you can focus on building the benefit to the business. Like most development issues, the real cost is in the maintenance. I fear that much of the work in this space is done by consultants because typically consultants help get a solution built and move on. Its not that consultants are bad, but because they can go from greenfield to greenfield project (I certainly have been guilty of this before), the pain of maintaining this code isn't always obvious. What happens when the database is overwhelmed with data. What happens when you try to add indexing to an existing application as the use cases change and mean that adding index hints is hard (though in SQL Server 2008 you can do this without modifying the calls).
That comes back to Doug Purdy and other folks in the twitterverse. What's the next wave of solutions out there? I admittedly haven't spent enough time playing with solutions like ActiveRecord, but they feel like dynamic classes which doesn't feel like it will solve the problem. I have heard that maybe getting away from relational databases is the solution, but the object database/non-SQL/BigTable solutions I've seen never seem to scale to high transaction systems or work well with reporting.
Your turn...what's your take?
|Vue.js by Example|
|Bootstrap 4 by Example|
|Intro to Font Awesome 5 (Free Course)|
|Designing RESTful Web APIs (new)|
|Building an API with ASP.NET Web API|
|Building an API with ASP.NET Core|
|Building a Web App with ASP.NET Core, MVC6, EF Core, Bootstrap and Angular|
|Less: Getting Started|
|Application Name||WilderBlog||Environment Name||Development|
|Application Ver||v4.0.30319||Runtime Framework||x86|
|App Path||D:\home\site\wwwroot\||Runtime Version||.NET Core 3.0.0|
|Operating System||Microsoft Windows 10.0.14393||Runtime Arch||X86|