EF Dependency Resolution


EF has historically taken a rather ad-hoc approach to runtime configuration and extensibility. The changes for EF6 described here and in the post covering code-based configuration are intended to replace this ad-hoc approach with some building blocks that will provide a common mechanism for configuration. In doing so they also allow EF to be more easily extended by extracting out services that can then be resolved to different implementations at runtime.

This spec describes low level building blocks

The components described in this spec are low level building blocks that will only be used in advanced scenarios. Developers wishing to make simple configuration changes from code should use the DbConfiguration class described in the code-based configuration spec. DbConfiguration provides a simple façade over the components described here.


The changes described in these specs address the following goals:

  • Provide a common mechanism and building blocks whereby aspects of existing EF functionality can be factored out or new functionality added in such a way that different implementations can be injected without the core EF code knowing about the specifics of these implementations.
  • Provide a unified mechanism for EF code to access configuration regardless of whether that configuration has been set in code (“code-based”) or in the application’s config file.
  • Ensure that configuration can be discovered by design-time tools such that actions such as running the Code First pipeline can be correctly performed by tools.
  • Allow, but not require, EF dependencies to be injected using the application developer’s Inversion-of-Control (IoC) container of choice.

Service Locator pattern

The most fundamental underlying building block here is the use of the Service Locator pattern as represented by the IDbDependencyResolver interface:

public interface IDbDependencyResolver
    object GetService(Type type, object key);
    IEnumerable<object> GetServices(Type type, object key);

At the most basic level, when EF needs an implementation of some interface or base class it will call GetService passing in the interface or base class type and will get back the implementation to use. Likewise, GetServices is used to get all implementations of a given service type for a given key.

IDbDependencyResolver is similar to the IDependencyResolver interfaces of ASP.NET MVC and Web API.

The resolver chain

Internally, EF maintains a list of classes that implement this interface and uses the Chain-of-Responsibility pattern to resolve services it needs from this chain. That is, it calls GetService on the first IDbDependencyResolver in the list. If this implementation returns null, then it calls GetService on the next. This continues until either a non-null object is returned or the last resolver in the chain is reached. This last resolver is always the “root” resolver which will resolve any service needed by EF with a default implementation if none of the other resolvers in the chain resolve the service first.

In practical terms this means that if you use EF6 out of the box without doing anything then all services needed by EF are resolved by the root resolver to the EF defaults. If you want to change one or more of the defaults then you can add one or more new IDependencyResolver implementations to the chain. EF will then resolve the service using the resolver(s) you have added and will no longer use the defaults provided by the root resolver. For any services that your resolver(s) do not handle, the defaults provided by the root resolver will still be used.

For example, to change the default connection factory you can write a DbConfiguration class like so:

public class MyAppConfiguration : DbConfiguration
    public MyAppConfiguration()
        AddDependencyResolver(new MyDependencyResolver());

public class MyDependencyResolver : IDbDependencyResolver
    public object GetService(Type type, object key)
        if(type == typeof(IDbConnectionFactory))
            return new MyConnectionFactory();

        return null;

    public IEnumerable<object> GetServices(Type type, object key)
        var service = GetService(type, key);
        return service == null ? Enumerable.Empty<object>() : new[] { service };

More details about DbConfiguration can be found in the post on code-based configuration (including information about performing configuration without having to worry about resolvers).

We also provide a SingletonDependencyResolver implementation of IDbDependencyResolver that returns the given object when GetService is called for the provided generic type and otherwise returns null. This makes it easy to override a specific dependency without having to write your own resolver:

public class MyAppConfiguration : DbConfiguration
    public MyAppConfiguration()
        AddDependencyResolver(new SingletonDependencyResolver<IDbConnectionFactory>(new MyConnectionFactory()));

What is the key?

This key argument is optionally used to provide information to the resolver about the requested service. For example, the provider invariant name string  is passed as a key when when GetService is used to request an EF provider. A GetService implementation must then return the provider for the given invariant name.

The type and semantics of the key object, if any, is documented for each service that may be requested.


In most situations EF just needs one implementation of a service and therefore calls GetService as described above. However, sometimes EF needs all implementations of a service for a given key. For example, on startup EF will ask for all IDbInterceptor implementations so that it can then dispatch to all registered interceptors. In this situation EF will call GetServices instead of GetService. Each resolver should return a enumeration containing all services of the given type and for the given key that it can provide. If it can’t provide any then it should return an empty enumeration. This is shown in the code example above.

Note that GetServices should not return all services for all keys. It should still only return services for the given key.

Default resolvers

Sometimes it may be desirable to configure a service that will be used only if no other service for the given type and key is resolved. For example, an EF provider may want to configure a default connection factory to be used only if the application has not configured the use of a different connection factory. This can be done using the AddDefaultResolver method instead of the normal AddDependencyResolver method. AddDefaultResolver places the given resolver below other resolvers in the chain-of-responsibility and hence will only be called if some other resolver has not already resolved the service.

Isn’t Service Locator an anti-pattern?

Some people consider Service Locator to be an anti-pattern. This is for two main reasons:

  • It can lead to runtime errors if the locator does not know about and hence does not resolve a service, and it is often hard find out which services a locator must resolve.
  • No context is provided for the code attempting to resolve the service.

The first issue is addressed in the EF design through the resolver chain and the associated root resolver which is designed to resolve any dependencies not handled by other resolvers. This means that so long as the EF team updates the root resolver whenever a new service is added then it doesn’t matter that other resolver implementations don’t know about or handle the new service. Put another way, when you implement IDbDependencyResolver you don’t have to worry about resolving everything, you just resolve the services you are interested in.

The second issue is addressed in two ways. First, the key object provides context about the service being resolved. (The word “context” is used here in its general sense; it does not necessary refer to a DbContext/ObjectContext.) Also, in the design for scoping (see below) the key provides context information about the scope of the resolver being created.

How do I know what services can resolved?

The public services that can be resolved by an IDbDependencyResolver are documented on MSDN.

Generic extension methods

Only one GetService method and one GetServices method are defined on IDbDependencyResolver to make it easy to implement this interface without lots of duplicate code. However, the most common way of calling one of the methods is to use one of the extension methods:

public static T GetService<T>(this IDbDependencyResolver resolver, object key)
public static T GetService<T>(this IDbDependencyResolver resolver)
public static object GetService(this IDbDependencyResolver resolver, Type type)

public static IEnumerable<T> GetServices<T>(this IDbDependencyResolver resolver, object key)
public static IEnumerable<T> GetServices<T>(this IDbDependencyResolver resolver)
public static IEnumerable<object> GetServices(this IDbDependencyResolver resolver, Type type)

For example, this:

var provider = resolver.GetService<DbProviderServices>("System.Data.SqlClient");

Is equivalent to this:

var provider = (DbProviderServices)resolver.GetService(typeof(DbProviderServices), "System.Data.SqlClient");

What about scopes?

Imagine a situation where a DbContext instance depends on a service object that must only live while the context exists and must be disposed when the context is disposed. We currently don’t have an services like this, but it is conceivable that we will in the future. We have therefore designed and prototyped a way to handle this and it is described in the EF design meeting notes for September 27, 2012.

Extensibility and open source contributions

Let’s say you want to add to or change EF behavior in some way. With the open source model you could submit a pull request, and in a lot of cases we are likely to accept it. However, there may be cases where the change is not appropriate for the core EF code for a number of reasons:

  • It might break existing applications
  • It might be an uncommon scenario that is useful to you but not the majority
  • Your implementation might work for you but not be general or robust enough to become a supported part of the product

In such situations you may still be able to make the change by creating an interface that is resolved using the mechanisms described above. We are very likely to accept such a changes since it is generally useful to increase the extensibility of the code in this way. With such a change in EF you will then be able to add the functionality you need without further changes to the EF code. If you choose you can still make your functionality available to others so that they can benefit from it.

Related information

The main entry point for EF dependency resolution is the DbConfiguration class which is described in a separate post on code-based configuration. We intend to also publish a post describing how to use IDbDependencyResolver with an off-the-shelf IoC container.

Last edited Aug 2, 2013 at 5:24 PM by ajcvickers, version 6