Entity Framework has always had a mixed reputation, with some developers loving it while other compared it unfavorably to NHiberante, LINQ-to-SQL, and the various micro-ORMs. But the early impressions of EF Core have been particularly bad and continue to frustrate even those who appreciated the original Entity Framework.

SQL Generation

At the top of the list is the poor support for SQL generation. EF Core 2.0 still doesn’t support basic SQL constructs such as grouping. While it isn’t unusual for ORMs to not support advanced features such as Window Functions, the inability to handle “GROUP BY” is considered to be unacceptable by many developers.

According to the release notes, this version has “increased the number of patterns that can be translated to SQL, so many queries that triggered client-side evaluation in previous versions will no longer do it in 2.0”. However, they still haven’t documented what those patterns are so we recommend that developers carefully verify each query. Alternately, you can disable client-side evaluation.

Microsoft has indicated that grouping support is being planned for EF Core 2.1.

Complex Types

In Entity Framework you have the concept of Complex Types. Essentially these allow you to create a child object that is mapped to the same table as its parent. One use of a complex type would be to separate commonly used audit fields from the regular data fields.

EF Core doesn’t support complex types, but instead has “owned” or “child” types. Diego B Vega of Microsoft claims that “Owned types in EF Core 2.0 support a superset of the scenarios supported by complex types in previous versions of EF”. However, they have a different syntax and design so porting complicated models may require some research.

Lazy Loading

Lazy loading is considered to be a bad idea by many because it can lead to performance problems (e.g. 1+N queries) and runtime failures (e.g. disposed contexts). Nonetheless, it is a very popular feature in Entity Framework and some people think that no library can truly be called an ORM without it. Understandably, they are upset that lazy loading is being delayed until EF Core 2.1.

Rowan Miller of Microsoft did mention the possibility of creating your own lazy loading scheme in the meantime:

Just to add one data point to the discussion. Lazy Loading isn't going to be in 2.0 but we are adding some features that are groundwork for implementing it. The biggest one is Life Cycle Hooks, which combined with the EntityEntry APIs we added in 1.1, will allow a rudimentary roll-your-own lazy loading pattern.

Life cycle hooks for object materialization are currently marked as a “stretch goal” for EF Core 2.1.

Table Per Type

Table Per Type Inheritance (TPT) allows one logical record to be split over multiple database tables. In this design, an abstract base class represents one table. Then each subclass of that has its own table. This allows the application to see a logical view of the data while the database gets a more efficient design.

Unfortunately, TPT has a reputation for having significant performance problems in Entity Framework. Here is one complaint on User Voice:

For TPT inheritance, the more subclasses you add, the time it takes to generate SQL, and the complexity of the SQL query itself, become unmanageable. With a simple base class (5 or 6 fields), and around 30 simple subclasses (two or three fields a piece), it takes almost two minutes to generate the SQL (ObjectQuery.ToTraceString()) and execute it on the server. EF generates almost 8000 lines of SQL for a simple select query on the base class. This is because the SQL generated is a mess of crazy subselects, joins, and unions. Even with empty tables (so that a query would return no data), it takes that long to generate and execute the SQL.

Many of these issues have been fixed, but EF 6 is considered to be an obsolete library and no further work is planned for it.

TPT isn’t supported at all in EF Core. There is a backlog item for it, but no specific plans to implement it. This is a problem for developers currently using TPT in EF, as major changes are needed to work-around this issue.

Table per Concrete Class

A closely related feature to TPT is TPC or Table per Concrete Class. Like TPT, this uses inheritance in the application to simply class design. However, on the database side there is no table that directly represents the abstract base class. Rather, every concrete (i.e. non-abstract) subclass is fully represented by its own table that includes the columns from both the subclass itself and any inherited classes.

While also not supported by EF Core, there doesn’t seem to be a lot of call for TPC. This is probably due to the fact that you can get the same net effect replacing the abstract base class with an abstract interface. The properties in the base class with have to be cut-and-pasted into each concrete class, but which is tedious but not difficult or error prone.

Stored Procedures

Another missing feature is full support for stored procedures. While they can be abused, stored procedures are one of the most powerful tools offered by relational database servers. In many scenarios, it is much more efficient to process all of the data in the database than it would be to try to transport the data over the network to the application. This is especially true when doing so would result in multiple round-trips while tables are locked inside a transaction.

This seems like it would be an easy feature to implement, as the SQL generation is quite simple. Even InfoQ’s demonstration of a micro ORM using the DLR included it using less than 200 lines of code. Yet it remains on the backlog with no indication as to when it will be implemented.

It may be a lower priority because work-arounds do exist. Anuraj P demonstrates how to call stored procedures in EF Core and some of the pain points such as the lack of named parameters.

Spatial Types

Working with spatial data is still not supported by EF Core. It is on the road map as a high priority item, but not tied to a specific release yet.

Not all news has been bad. In Part 2 of this series we’ll discuss the new features that did make it into EF Core 2.0.