2

I'm trying to move my EF6 configuration from myexe.exe.config to code as a workaround for the empty DbProviderFactories node in machine.config-issue (described here: https://stackoverflow.com/a/24273922/600559). I don't want to change the machine.config file.

I have read the Code-Based Configuration (EF6 onwards).

I have tried implementations like this: https://stackoverflow.com/a/23130602/600559, however I cannot get it to work. Does anyone have a working EF6/SQL CE/code-based configuration solution?

Here's my my changes (from a working .config solution to a code based solution): New class added:

public class DatabaseConfiguration : DbConfiguration
{
    public DatabaseConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlServerCe.4.0", () => new DefaultExecutionStrategy());
        SetProviderFactory("System.Data.SqlServerCe.4.0", new SqlCeProviderFactory());
        SetProviderServices("System.Data.SqlServerCe.4.0", SqlCeProviderServices.Instance);
    }
}

Then the system.data and entityFramework node in the .config-file is removed.

Now this works, however the machine.config files is read: If a have the <DbProviderFactories/> in machine.config I get this exception:

Exception

So the real problem is not that the code based configuration does not work, the problem is that the machine.config configuration is still being read and causes issues. Anyone knows how to solve this?

Community
  • 1
  • 1
Morten Frederiksen
  • 5,114
  • 1
  • 40
  • 72

1 Answers1

2

Found a solution. Implementing a IDbProviderFactoryResolver that does not read from the machine.config file:

  public class CodeBasedDatabaseConfiguration : DbConfiguration
  {
    public CodeBasedDatabaseConfiguration()
    {
      SetExecutionStrategy("System.Data.SqlServerCe.4.0", () => new DefaultExecutionStrategy());
      SetProviderFactory("System.Data.SqlServerCe.4.0", new SqlCeProviderFactory());
      SetProviderServices("System.Data.SqlServerCe.4.0", SqlCeProviderServices.Instance);
      SetProviderFactoryResolver(new CodeBasedDbProviderFactoryResolver());
    }
  }

  internal class CodeBasedDbProviderFactoryResolver : IDbProviderFactoryResolver
  {
    private readonly DbProviderFactory sqlServerCeDbProviderFactory = new SqlCeProviderFactory();

    public DbProviderFactory ResolveProviderFactory(DbConnection connection)
    {
      var connectionType = connection.GetType();
      var assembly = connectionType.Assembly;
      if (assembly.FullName.Contains("System.Data.SqlServerCe"))
      {
        return sqlServerCeDbProviderFactory;
      }
      if (assembly.FullName.Contains("EntityFramework"))
      {
        return EntityProviderFactory.Instance;
      }
      return null;
    }
  }
Morten Frederiksen
  • 5,114
  • 1
  • 40
  • 72
  • 1
    That is not a robust solution. Use my EntityFramework.SqlServerCompact.PrivateDeployment NuGet package, which would save you some code to maintain, and be robust - with you current solution you will run into runtime errors if a different version of the 4.0 runtime is installed in GAC on the target PC, as the version of the ADO.NET provider (System.Data.SqlServerCe.dll) will attempt to load unmanaged dll files of the wrong version. – ErikEJ Apr 21 '15 at 16:13
  • @ErikEJ - Thanks for your comments. I'm reading your blog post http://erikej.blogspot.dk/2013/11/entity-framework-6-sql-server-compact-4_25.html and I'm getting scared. I have seen private deployment of SqlCE as very simple - never thought about GAC conflicts. I will take a look at EntityFramework.SqlServerCompact.PrivateDeployment. – Morten Frederiksen Apr 21 '15 at 18:10
  • Thanks, Morten. The important post is actually http://erikej.blogspot.dk/2014/10/entity-framework-6-and-sql-server.html – ErikEJ Apr 21 '15 at 18:26
  • @ErikEJ - my bad - it was the http://erikej.blogspot.dk/2014/10/entity-framework-6-and-sql-server.html post i meant – Morten Frederiksen Apr 21 '15 at 18:29