Caution

This documentation is for EF Core. For EF6.x and earlier release see http://msdn.com/data/ef.

Writing a Database Provider

In this article

EF Core is designed to be extensible. It provides general purpose building blocks that are intended for use in multiple providers. The purpose of this article is to provide basic guidance on creating a new provider that is compatible with EF Core.

Tip

EF Core source code is open-source. The best source of information is the code itself.

Tip

This article shows snippets from an empty EF provider. You can view the full stubbed-out provider on GitHub.

DbContext Initialization

A user’s interaction with EF begins with the DbContext constructor. Before the context is available for use, it initializes options and services. We will example both of these to understand what they represent and how EF configures itself to use different providers.

Options

Microsoft.EntityFrameworkCore.Infrastructure.DbContextOptions is the API surface for users to configure DbContext. Provider writers are responsible for creating API to configure options and to make services responsive to these options. For example, most providers require a connection string. These options are typically created using DbContextOptionsBuilder.

Services

System.IServiceProvider is the main interface used for interaction with services. EF makes heavy use of dependency injection (DI). The ServiceProvider contains a collection of services available for injection. Initialization uses DbContextOptions to add additional services if needed and select a scoped set of services that all EF operations will use during execution.

See also Understanding EF Services.

Note

EF uses Microsoft.Extensions.DependencyInjection to implement dependency injection. Documentation for this project is available on docs.asp.net.

Plugging in a Provider

As explained above, EF uses options and services. Each provider must create API so users to add provider-specific options and services. This API is best created by using extension methods.

Tip

When defining an extension method, define it in the namespace of the object being extended so Visual Studio auto-complete will include the extension method as a possible completion.

The Use Method

By convention, providers define a UseX() extension on DbContextOptionsBuilder. This configures options which it typically takes as arguments to method.

optionsBuilder.UseMyProvider("Server=contoso.com")

The UseX() extension method creates a provider-specific implementation of IDbContextOptionsExtension which is added to the collection of extensions stored within DbContextOptions. This is done by a call to the a hidden API IDbContextOptionsBuilderInfrastructure.AddOrUpdateExtension.

An example implementation of the “Use” method
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    public static class MyProviderDbContextOptionsExtensions
    {
        public static DbContextOptionsBuilder UseMyProvider(this DbContextOptionsBuilder optionsBuilder,
            string connectionString)
        {
            ((IDbContextOptionsBuilderInfrastructure) optionsBuilder).AddOrUpdateExtension(
                new MyProviderOptionsExtension
                {
                    ConnectionString = connectionString
                });

            return optionsBuilder;
        }
    }

Tip

The UseX() method can also be used to return a special wrapper around DbContextOptionsBuilder that allows users to configure multiple options with chained calls. See SqlServerDbContextOptionsBuilder as an example.

The Add Method

By convention, providers define a AddX() extension on EntityFrameworkServicesBuilder. This configures services and does not take arguments.

EntityFrameworkServicesBuilder is a wrapper around ServiceCollection which is accessible by calling GetInfrastructure(). The AddX() method should register services in this collection to be available for dependency injection.

In some cases, users may call the Add method directly. This is done when users are configuring a service provider manually and use this service provider to resolve an instance of DbContext. In other cases, the Add method is called by EF upon service initialization. For more details on service initialization, see Understanding EF Services.

A provider must register an implementation of IDatabaseProvider. Implementing this in-turn requires configuring several more required services. Read more about working with services in Understanding EF Services.

EF provides many complete or partial implementations of the required services to make it easier for provider-writers. For example, EF includes a class DatabaseProvider<TProviderServices, TOptionsExtension> which can be used in service registration to hook up a provider.

An example implementation of the “Add” method
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    public static class MyProviderServiceCollectionExtensions
    {
        public static IServiceCollection AddEntityFrameworkMyProvider(this IServiceCollection services)
        {
            services.AddEntityFramework();

            services.TryAddEnumerable(ServiceDescriptor
                .Singleton<IDatabaseProvider, DatabaseProvider<MyDatabaseProviderServices, MyProviderOptionsExtension>>());

            services.TryAdd(new ServiceCollection()
                // singleton services
                .AddSingleton<MyModelSource>()
                .AddSingleton<MyValueGeneratorCache>()
                // scoped services
                .AddScoped<MyDatabaseProviderServices>()
                .AddScoped<MyDatabaseCreator>()
                .AddScoped<MyDatabase>()
                .AddScoped<MyEntityQueryableExpressionVisitorFactory>()
                .AddScoped<MyEntityQueryModelVisitorFactory>()
                .AddScoped<MyQueryContextFactory>()
                .AddScoped<MyTransactionManager>());

            return services;
        }
    }

Next Steps

With these two extensibility APIs now defined, users can now configure their “DbContext” to use your provider. To make your provider functional, you will need to implement other services.

Reading the source code of other providers is an excellent way to learn how to create a new EF provider. See Database Providers for a list of current EF providers and to find links to their source code (if applicable).

Microsoft.EntityFrameworkCore.Relational includes an extensive library of services designed for relational providers. In many cases, these services need little or no modification to work for multiple relational databases.

For more information on other internal parts of EF, see Internals.