Surely, it canât be used for production
Throughout my, admittedly short career, Iâve heard about half a dozen developers say that EF Core shouldnât be used for production services. That itâs simply a gimmick that junior developers use for the projects, because they wouldnât have to learn âproperâ SQL. Or, better yet, is completely incompatible without their workflow.
Is that actually true, though? Surely, they werenât just saying that because of theyâve heard it somewhere. Iâll list some concerns Iâve heard and read people mention, when they talk about why they donât use EF Core.
âEntity Framework Core requires you to use migrationsâ
The most common misconception Iâve heard comes from three different lead developers, all claiming that EF Core requires migrations. From what I can read from the documentation, is has never been a requirement. Itâs simply a feature, which you can opt in to use for your project. Although, I can see where the confusion comes from. The official âGetting Startedâ documentation only mentions it briefly:
You can install tools to carry out EF Core-related tasks in your project, like creating and applying database migrations, or creating an EF Core model based on an existing database.
Note that the original documentation has no emphasis on âcan.â
In the later sections where you scaffold the database, it isnât pointed out as being optional:
The following steps use migrations to create a database.
In reality, EF Core places no restrictions on how you create and manage your database schema. Only that they match when requested. You can just as well migrate database schemas manually, should you really want to.
To be fair, thereâs still an argument to be made whether you should use migrations for your project. But, Iâll let your teams decide that.
âEntity Framework Core generates unoptimized SQLâ
When you run some SQL query using EF Core, you might be able to glean the resulting query from the logs. As an example, it might look something like this:
SELECT [i].[ID], [i].[FirstName], [i].[HireDate], [i].[LastName], [o].[InstructorID]
FROM [Instructor] AS [i]
LEFT JOIN [OfficeAssignments] AS [o] ON [i].[ID] = [o].[InstructorID]
LEFT JOIN (
SELECT [c].[CoursesCourseID], [c].[InstructorsID], [c0].[CourseID], [c0].[Credits], [c0].[Department]
FROM [CourseInstructor] AS [c]
INNER JOIN [Course] AS [c0] ON [c].[CoursesCourseID] = [c0].[CourseID]
INNER JOIN [Departments] AS [d] ON [c0].[DepartmentID] = [d].[DepartmentID]
) AS [t] ON [i].[ID] = [t].[InstructorsID]
ORDER BY [i].[LastName], [i].[ID], [o].[InstructorID], [t].[CoursesCourseID], [t].[InstructorsID],
And your first reaction might be something like âwho writes SQL like this?â In reality, no one does. The query generators does. And as unreadable as this might seem, the query optimizer really doesnât care about whether the query is human readable.
Iâve heard one developer say that EF Core uses sub-queries, as opposed to joins, which are worse for performance. In the example above, which was lifted from this StackOverflow answer, it uses both. Relational databases have been a thing for many decades, so itâs naĂŻve to assume that nothing has changed since them. Query optimizers have become much more performant and efficient over many years, to where Postgres even uses genetic algorithms to optimize queries. And that was introduced more than 20 years ago!1
My point is, whether EF Core writes more or less efficient queries, it shouldnât really matter. If anything, the difference would only be marginal and I personally donât want to compete against hundreds (maybe thousands) of smart developers and decades of compiler experience.
And if you really are smarter than the compiler, then you wouldnât be reading this post.
âYou canât use Entity Framework Core for complex schemasâ
EF Core actually has pretty good support for more complex schemas, such as lists, inherited types, multiple primary keys, keyless types, all types of relationships, and more. If thereâs some feature that EF Core has no support for, you can still take use of EF Core. It just means that you might not have first-class support in migrations, querying, etc.
If you really need first-class support, and you claim that your schema isnât actually just overly complicated, you can still use good old fashioned SQL:
var blogs = context.Blogs
.FromSql($"SELECT * FROM dbo.Blogs")
.ToList();
You can even pass parameters to the query, without having to worry about SQL injection, as it uses .NETâs new FormattableString type, which are safe against SQL injection attacks.
var username = "johndoe";
var blogs = context.Blogs
.FromSql($"SELECT * FROM [Blogs] WHERE [User] = {username}")
.ToList();
For more information, read the official documentation about SQL queries in EF Core.
If none of thatâs your cup of tea, nothing is stopping you from Dapper along with EF Core.
Footnotes
Well, at least since Postgres 7.2, which is from 2002: https://web.mit.edu/cygwin/cygwin_v1.3.2/usr/doc/postgresql-7.1.2/html/geqo.html ^