Although EF Core seems to be the most popular ORM in the .NET world in these days – and I for sure won’t contradict it –, there are still some functionality missing, specially if we compare it with other ORMs that also exist, NHibernate coming obviously to my mind. This post is a reflection about that, it is in no way a comparison with other ORMs, in particular, NHibernate, it’s more a wish list for EF Core. I still follow and love NHibernate, and it’s still, in many ways, way ahead of EF Core, but that’s not what I’ll be writing about.
Primary Key Generation
EF Core currently only supports the following primary key generation strategies:
Identity/autoincrement (on databases that support it)
GUID/uniqueidentifier (on databases that support it)
Sequence-based (on databases that support it)
HiLo (SQL Server only)
For GUIDs, EF Core automatically generates, on the client-side, a new value before inserting, which is nice.
HiLo is a great pattern for generating primary keys, but, unfortunately, the way Microsoft implemented it, resorting to database sequences, makes it database-specific – currently, SQL Server only. If it were implemented with just standard DML commands, it could be made database-agnostic, for the benefit of all.
I dare say that EF Core is slightly biased towards SQL Server and, even more, that most SQL Server folks are used to having IDENTITY as their default primary key generation strategy. While this is fine, it does prevent batch insertions, because it requires obtaining the generated primary key after each inser (SELECT SCOPE_IDENTITY()). If we have a client-generated primary key, batch insertion is possible, which can be a great benefit.
I’d like to have a truly extensible primary key generation mechanism on EF Core. Maybe something for the future.
Currently, EF Core only supports one type of collection. It can be lazy loaded, in which case, you need to declare it as ICollection<T> or IList<T>, or not, but that is it. You can’t have collections of primitive types without using a value converter. Plus, you don’t have semantic collections such as sets or bags, or indexed collections such as lists or maps.
Table Inheritance Patterns
There are three canonical table inheritance patterns:
Currently, TPH and TPT are already supported, but TPC is not. There are plans to introduce it in the future (https://github.com/dotnet/efcore/issues/3170)
Currently there’s no way to map a column to a SQL expression, which could be very handly. True, we can have a whole entity coming as the result of a view, or a raw SQL, but this is a different thing. Of course, that property would not be persisted.
Expressions for CUD Operations
Another useful operation, the ability to use raw SQL – which could even be a stored procedure call – for Create, Update, and Delete (CUD) operations. This is also currently scheduled by the team for a future release (https://github.com/dotnet/efcore/issues/245).
Strongly Typed DML Operations
One thing that would be nice and already exists on other ORMs is the ability to batch perform DML operations from LINQ queries, for example, UPDATEs and DELETEs. Take this hypothetical strongly typed delete on top of a LINQ query, for example:
var deletedPosts = ctx.Posts.Where(p => p.Timestamp.Date < DateTime.Today.AddDays(-365)).Delete();
Much better than writing SQL as hardcoded strings, don’t you think? Yes, I do know that there are third-party extensions out there that already do this, but it would be nice to have this built-in. It’s being tracked for future implementation (https://github.com/dotnet/efcore/issues/795).
Some lifecycle events – such as EF 6’s ObjectMaterialized and SavingChanges - are conspicuously missing. This can be useful, for example, to do something on an entity after it is loaded (hydrated) from the database. Fortunately, there are plans to introduce them (https://github.com/dotnet/efcore/issues/15911).
As a I said, these are just some thoughts on nice-haves for EF Core. Some of them are already on the EF Core team’s list, and some are not. There are many more, see the whole plan for v7.0 here and do submit your own suggestions here. As usual, I’d love to hear your thoughts on this, so let’s have them!