Jakov
Jakov

Reputation: 749

No db context provider has been configure for this DbContext... although it has

Have a solution with 3 assemblies: Data, Domain and Web. Data holds the context, Web is a .NET Core WebAPI app, and they're all in the same solution directory. I'm also using Postgre as the database.

Here's my ConfigureServices method in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    string connectionString = Configuration.GetConnectionString("DefaultConnection");
            ...
    services.AddDbContext<WebStoreContext>(
        options => options.UseNpgsql(
            connectionString,
            (providerOptions) =>
            {
                providerOptions.CommandTimeout(20);
                providerOptions.MigrationsAssembly("WebStore.Data");
            }));

    services.AddMvc();
            ...
}

Notice how a database provider has been configured by using AddDbContext and passing the optionsAction parameter.

Now I've created an initial migration for the db, using the command line ef tool. I've cd-ed into WebStore.Data and ran:

dotnet ef --startup-project ..\WebStore.Web migrations add IntializeDb

That's all good.

The problem begins when I try to, from the same directory, run:

dotnet ef database update

No parameterless constructor was found on 'WebStoreContext'. Either add a parameterless constructor to 'WebStoreContext' or add an implementation of 'IDbContextFactory' in the same assembly as 'WebStoreContext'.

The above error I get before I declare a parameterless constructor in my DbContext derived class, and the below error after I declare one:

No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.

So it seems to me like the paramterless constructor keeps getting called despite me providing a DbContextOptions instance.

So then I tried this:

//parameterless constructor calling the one accepting the DbContextOptions argument
public WebStoreContext() : this(new DbContextOptionsBuilder<WebStoreContext>()
.UseNpgsql("UserID=****;Password=****;Host=localhost;Port=****;Database=webstore;Pooling=true;")
.Options){ }

and got this:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileLoadException: Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Still trying to figure out what's going on here. Help would be greatly appreciated.

EDIT: I applied Shay Rojansky's solution and it worked, although I had the following issue:

System.IO.FileLoadException: Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) File name: 'System.Diagnostics.DiagnosticSource, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' at Microsoft.EntityFrameworkCore.Infrastructure.RelationalServiceCollectionExtensions.AddRelational(IServiceCollection services) at Microsoft.Extensions.DependencyInjection.NpgsqlEntityFrameworkServicesBuilderExtensions.AddEntityFrameworkNpgsql(IServiceCollection services) at Microsoft.EntityFrameworkCore.Internal.ServiceProviderCache.<>c__DisplayClass4_1.b__2(Int64 k) at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) at Microsoft.EntityFrameworkCore.DbContext.InitializeServices() at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory) at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType) at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_1.<.ctor>b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

To which the solution is adding this to the .csproj file:

<PropertyGroup>
        <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup>

This happens apparently due to a bug.

Upvotes: 0

Views: 1487

Answers (3)

Rtype
Rtype

Reputation: 915

I found the easiest solution to this is to remove the default constructor from the context. Just have a single constructor with DBContentOptions or DBContentOptions<> as the parameter that is then passed into the base class.

public class ApplicationDbContext : DbContext>
{
    #region Constructor
    public ApplicationDbContext(DbContextOptions options) : base(options) { }
    #endregion
}

but agreed this isn't ideal. Esp if you need to use the context outside of EF unity IOC.

Hopefully this will help others out there.

Upvotes: 1

cycsky
cycsky

Reputation: 1

I've encountered this problem, no need to change anything but add the --startup-project parameter when you run any commands. ex.
dotnet ef database update --startup-project ..\WebStore.Web

Upvotes: 0

Shay Rojansky
Shay Rojansky

Reputation: 16722

Try adding an OnConfiguring method to your context, as suggested by the EF Core getting started docs:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    optionsBuilder.UseNpgsql("...");
}

Upvotes: 1

Related Questions