CHAPTER 7
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.
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.
This is probably obvious, but still people sometimes forget about it.
You need to use SQL for this. Any nontrivial queries over DateTime, DateTimeOffset, TimeSpan, or using the Math static methods will fail.
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.
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.
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.
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.
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.
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.
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); } |
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"]); } } |