Search code examples
entity-framework-6mefautofacsqlclient

MEF register EntityFramework.SqlServer for provider System.Data.Client


We have a multi tier app that have a lot of dependencies. We use Autofac and MEF so that all the components can register their own dependencies in init modules. That way, the "higher" components doesn't have to know all the dependencies graph. It just register the component it needs, and the rest comes along. At the higher level, there is a WCF facade app that imports almost all of our DLL and register them with Autofac. It works fine, but since the repository layer depends on EntityFramework, I get the infamous error :

No Entity Framework provider found for the ADO.NET provider with invariant name 'System.Data.SqlClient'. Make sure the provider is registered in the 'entityFramework' section of the application config file

The only way I found not to have this error is to directly reference EntityFramework.SqlServer in the WCF facade project. But I'd like to leave the responsabllity of this to the repo layer itself. So I would need a way to somehow load the dll and register the System.Data.SqlClient. Does anyone know a way to do so or am I just dreaming ? It's my first time with both Autofac and MEF and I'm far from an expert in DI.

Since it is highly conceptual, here is a little schema with source code to help you understand better : Conceptual map

Get readeable version here


Solution

  • Perhaps you could take a look at Code-Based Configuration.

    1. Create a custom DbConfiguration

      public class MyDbConfiguration : DbConfiguration 
      { 
          public MyDbConfiguration() 
          { 
              // Other configuration stuff like SetDefaultConnectionFactory
              SetProviderServices(
                  "System.Data.SqlClient", 
                  System.Data.Entity.SqlServer.SqlProviderServices.Instance);
          } 
      } 
      
    2. Add a DbConfigurationTypeAttribute to your DbContext

      [DbConfigurationType(typeof(MyDbConfiguration))] 
      public class MyDbContext : DbContext 
      { }
      

      or

      [DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")] 
      public class MyDbContext : DbContext 
      { }
      
    3. Remove entityFramework configuration from the app.config file

    Edit

    For your top level project to find assemblies referenced by your MEF components, if you're able/willing to add something to the app.config, maybe you could use something like:

    <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="Libs"/>
      </assemblyBinding>
    </runtime>
    

    It would still be a dependency, in a sense, but you do have to add a search path for MEF...

    https://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.110%29.aspx
    How can MEF resolve dependencies of assemblies that don't live at the root of the application?