CHAPTER 7
Common Pitfalls
Overview
Whenever you start using a new technology, there’s always the possibility that you will fall into one of its traps. Here I will list some of them.
Group By is performed in memory
In this version of Entity Framework Core, the translation of Group By to SQL hasn’t been implemented. The result is that EF will fetch all the records from the database and then perform the grouping in memory on the client-side, which is a performance nightmare. You will need to use plain SQL to execute your query, if you really need it.
Changes are not sent to the database unless SaveChanges is called
This is probably obvious, but still people sometimes forget about it.
No support for date and time or mathematical operations
You need to use SQL for this. Any nontrivial queries over DateTime, DateTimeOffset, TimeSpan, or using the Math static methods will fail.
No implicit loading
This is not implemented yet. You need to force the loading of all the collections and references you need by adding Include calls in your queries, or load them explicitly afterwards using Load. See the “ Explicit” section.
LINQ queries over unmapped properties
Visual Studio IntelliSense makes it very easy to write LINQ queries because it automatically shows all available properties. It may happen that some of these properties are not actually mapped. For example, they are read-only, calculated columns that are computed from other properties. Access to these properties cannot be translated to SQL queries, so any attempt to use them in an Entity Framework query will result in an exception.
Null navigation properties
If you have a null navigation property in a loaded entity, this is because you didn’t explicitly fetch it through a call to Include.
For more information, revisit the “Eager” section.
Cannot have non-nullable columns in single-table inheritance
When using the Single Table Inheritance pattern (the only supported inheritance pattern as of EF 1.1), you cannot have non-nullable properties in derived classes, because it all will be created in the same table, and they won’t exist for all derived classes.
Cannot use the integrated service provider in an infrastructure method
The Entity Framework Core context includes its own service provider. You can replace it when you build the context; otherwise you get a default one. You may be tempted to try to get services from it in one of the infrastructure methods like OnConfiguring or OnModelCreating, but you won’t be lucky, because you will get an exception. The service provider can only be accessed after the context is fully initialized, which includes these methods having run.
Using the integrated service provider requires a special constructor
You can register your EF contexts, for example, so that they are injected into an MVC controller. This is normally done in the ConfigureServices method of the Startup class through the AddDbContext extension method:
Code Listing 146
services.AddDbContext<ProjectsContext>(options => { options.UseSqlServer("<connection string>"); }); |
For this to work, however, you need to add a specific constructor to your context and call the base implementation:
Code Listing 147
public class ProjectsContext : DbContext { public ProjectsContext(DbContextOptions options) : base(options) { } } |
Otherwise, the included service provider will not be able to build your context.
Migrations need to go on a .NET Core project
You cannot have migrations on a .NET Standard project. If, for example, your context belongs in a .NET Standard project like “Domain Model” or similar, you will need to reference a .NET Core project (like “Web” or “Console Application”) where migrations are to be created:
Code Listing 148
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder .UseSqlServer(connectionString, b => b.MigrationsAssembly("Web")); base.OnConfiguring(optionsBuilder); } |
Contexts without parameterless constructors cannot be used in migrations
If you have a context that does not feature a public parameterless constructor, you need to implement a context factory so that it can be instantiated by the migrations tooling:
Code Listing 149
public class ProjectsContextFactory : IDesignTimeDbContextFactory<ProjectsContext> { public ProjectsContext CreateDbContext(string[] args) { var configurationBuilder = new ConfigurationBuilder() .AddJsonFile("appSettings.json", false); var configuration = configurationBuilder.Build(); return new ProjectsContext( configuration["ConnectionStrings:Projects"]); } } |
- 1800+ high-performance UI components.
- Includes popular controls such as Grid, Chart, Scheduler, and more.
- 24x5 unlimited support by developers.