EF6/SQL Server Compact, code-based configuration

2019-02-15 12:29发布

问题:

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:

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?

回答1:

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;
    }
  }