Is it possible to configure a custom provider for

2019-08-05 01:05发布

问题:

I am trying to setup automated migrations using migrate.exe that is provided in the EntityFramework v6 nuget package. My application uses a PostgreSQL database and uses a custom database provider (Npgsql), which requires additional configuration for EntityFramework.

Migrate.exe works successfully if I add the required configuration into the machine.config, however this is not a practical solution as it requires editing the machine.config everywhere the migrations are run. I also want to set this up as part of a build process in AppVeyor and I don’t think it is possible to edit the machine.config of an AppVeyor build server.

As an alternative to editing the machine.config I tried creating a migrate.exe.config file containing the required configuration alongside migrate.exe, but this does not work and results in the following error.

ERROR: The ADO.NET provider with invariant name 'Npgsql' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.

Is there another way to configure a custom provider for migrate.exe without using the machine.config?

For reference the additional configuration required is

<system.data>
  <DbProviderFactories>
    <remove invariant="Npgsql" />
    <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql" type="Npgsql.NpgsqlFactory, Npgsql" />
  </DbProviderFactories>
</system.data>
<entityFramework>
  <defaultConnectionFactory type="Npgsql.NpgsqlConnectionFactory, Npgsql" />
  <providers>
    <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFramework" />
  </providers>
</entityFramework>

回答1:

I just went through this (not specifically with AppVeyor, but I'm working towards automating my TeamCity build server) and was able to get it to work using Entity Framework 6.0.0.0. Here's the command I was running which resulted in the same error

.\migrate.exe
  MyProject.DataContracts.dll
  /ConnectionString:"server=localhost;user id=<myuserid>;password=<mypassword>;database=<mydatabase>"
  /connectionProviderName:Npgsql

The missing component was specifying the config file for my startup project, like so

.\migrate.exe
  MyProject.DataContracts.dll
  /startupConfigurationFile:"..\..\..\MyStartupProject\Web.config"
  /ConnectionString:"server=localhost;user id=<myuserid>;password=<mypassword>;database=<mydatabase>"
  /connectionProviderName:Npgsql

For reference, here are the relevant Npgsql sections from my Web.config

<system.data>
  <DbProviderFactories>
    <remove invariant="Npgsql" />
    <add name="Npgsql Data Provider" invariant="Npgsql" description="Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />
  </DbProviderFactories>
</system.data>

<entityFramework>
  <defaultConnectionFactory type="Npgsql.NpgsqlConnectionFactory, Npgsql.EntityFramework" />
  <providers>
    <provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, Npgsql.EntityFramework"/>
  </providers>
</entityFramework>

Hopefully this helps anyone landing on this question who doesn't want automatic database initialization as shown in the other answer. Cheers!



回答2:

I could not find another way to configure migrate.exe to use a custom provider.

The better solution in the end was to add a database initialiser into the applications entity framework configuration that will run the migrations automatically, instead of using migrate.exe.

<entityFramework>
  <contexts>
    <context type="Assembly.ApplicationDbContext, Assembly">
      <databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[Assembly.ApplicationDbContext, Assembly], [Assembly.Migrations.Configuration, Assembly]], EntityFramework" />
    </context>
  </contexts>
</entityFramework>