EF Core Compiled Models

Using compiled models can reduce EF Core's startup time for applications that have large models, usually consisting of hundreds or thousands of entity types and relationships.

  • Startup time refers to the time taken to execute the first operation on a DbContext when that particular DbContext type is used for the first time in the application.
  • It is important to note that creating an instance of the DbContext alone does not cause the EF model to be initialized.
  • Instead, the model is initialized when a typical first operation such as DbContext.Add or executing the first query is performed.

Install Tools

Compiled models are created using the dotnet ef command-line tool. You can install dotnet ef as either a global or local tool, but most developers prefer installing dotnet ef as a global tool using the following command:

language-csharp
|
dotnet tool install --global dotnet-ef

The following command will update the tool.

language-csharp
|
dotnet tool update --global dotnet-ef

Before you can use the tools on a specific project, you'll need to add the Microsoft.EntityFrameworkCore.Design package to it.

language-csharp
|
dotnet add package Microsoft.EntityFrameworkCore.Design

Generate Compiled Model

To generate the compiled model, you can use a new dbcontext optimize command:

language-csharp
|
dotnet ef dbcontext optimize

When the above command is executed successfully, you will see the following output.

language-csharp
|
C:\Users\Muhammad Waqas\Source\repos\EFCoreDemo\EFCoreDemo>dotnet ef dbcontext optimize
Build started...
Build succeeded.
Successfully generated a compiled model, to use it call 'options.UseModel(BookStoreContextModel.Instance)'. Run this command again when the model is modified.

You will also notice that a new folder CompiledModels is added in your Solution Explorer that contains several files. Let's open the context model file and you will see some auto-generated code as shown below.

language-csharp
|
// <auto-generated />
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;

#pragma warning disable 219, 612, 618
#nullable enable

namespace EFCoreDemo.CompiledModels
{
    [DbContext(typeof(BookStoreContext))]
    public partial class BookStoreContextModel : RuntimeModel
    {
        static BookStoreContextModel()
        {
            var model = new BookStoreContextModel();
            model.Initialize();
            model.Customize();
            _instance = model;
        }

        private static BookStoreContextModel _instance;
        public static IModel Instance => _instance;

        partial void Initialize();

        partial void Customize();
    }
}

This is a partial class with partial methods that can be implemented to customize the model as needed.

To use the compiled model, we need to configure the DbContext as shown below.

language-csharp
|
public class BookStoreContext : DbContext
{
    public DbSet<Author> Authors { get; set; }
    public DbSet<Book> Books { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseModel(BookStoreContextModel.Instance)
            .UseSqlServer(@"Data Source=(localdb)\ProjectsV13;Initial Catalog=BookStoreDb;");
    }
}

Limitations

There are certain limitations associated with compiled models:

  • Global query filters are not supported
  • Lazy loading and change-tracking proxies are not supported
  • Custom IModelCacheKeyFactory implementations are not supported, but multiple models can be compiled and loaded as needed
  • The model must be updated manually whenever there is a change in its definition or configuration.

Compiled models should only be used when EF Core startup time is excessively long. It is usually not worthwhile to compile small models. If any of these features are essential for your project, please vote for the relevant issues linked above.


Date Modified: 2023-02-16
Author:

Edit this page in GitHub

Got any EF Core Question?