locked
EF Core - InvalidOperationException: No database provider has been configured for this DbContext RRS feed

  • Question

  • User-1350516731 posted

    Hi all! I have this message after my application is starting and fetching data from db.

    InvalidOperationException: 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<TContext> object in its constructor and passes it to the base constructor for DbContext.

    • Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
    • Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
    • Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
    • Microsoft.EntityFrameworkCore.DbContext.get_Model()
    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityType()
    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.CheckState()
    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityQueryable()
    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.System.Linq.IQueryable.get_Provider()
    • Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.AsNoTracking<TEntity>(IQueryable<TEntity> source)
    • testweb.Startup+<>c+<<Configure>b__3_1>d.MoveNext() in Startup.cs
    • temp = bag.Account.AsNoTracking().First();

    • Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
    • Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
    public class Startup
        {
    
            public Startup(IConfiguration configuration)
            {
    
                ConnectionString = Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(configuration, "SqlServer");
            }
             public static string ConnectionString;
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddDbContext<TotalForumContext>(options => options.UseSqlServer(ConnectionString));
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                app.UseRouting();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapGet("/", async context =>
                    {
                        Account temp;
                        
                         using(var bag = new TotalForumContext())        
                       temp = bag.Account.AsNoTracking().First();
                       await context.Response.WriteAsync(temp.Nick);
                
                    });
                });
            }
        }
    public partial class TotalForumContext : DbContext
        {
       public TotalForumContext()
       {}
    
            public TotalForumContext(DbContextOptions<TotalForumContext> options)
                : base(options)
            {
            }
    
            public virtual DbSet<Account> Account { get; set; }
    
    }
    {
      "ConnectionStrings": {
        "SqlServer": "Server=localhost; Database=TotalForum; User Id=forumadminuser; Password=password"
      }
    }
     <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.3" />
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.3" />
      </ItemGroup>

    What did happen? Why that doesn't work? Thank you.

    Wednesday, April 8, 2020 6:23 PM

Answers

  • User475983607 posted

    You did not pass the connection string option to the context. 

    But, ASP.NET Core uses constructor dependency injection.   This concept is covered in every ASP.NET Core getting started tutorial and the Core SDK project templates have sample code that illustrate the same.  The pattern has the following format.

        public class HomeController : Controller
        {
    
            private readonly efmvctestContext _db;
            public HomeController(efmvctestContext db)
            {
                _db = db;
            }

    Once properly configured you can use the content in all the Actions methods.

            [HttpGet]
            public IActionResult Index()
            {
               var results = _db.Person.Where(p => p.BusinessEntityId == 1);
               return View(results);
            }

    I recommend going through the Getting Started tutorials in this site which covers these basic constructs.

    https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/?view=aspnetcore-3.1

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, April 11, 2020 8:32 PM

All replies

  • User475983607 posted

    Please follow the standard pattern below or read the official documentation.

        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllersWithViews();
    
                services.AddDbContext<TotalForumContext>(options => 
                    options.UseSqlServer(Configuration.GetConnectionString("SqlServer")));
    
            }

    Wednesday, April 8, 2020 6:48 PM
  • User1120430333 posted

    Did you leave any code in the OnConfiguring(DbContextOptionsBuilder optionsBuilder), which overrides the dependency injection of the connectionstring established at Startup()?

    Wednesday, April 8, 2020 6:58 PM
  • User-1350516731 posted

    I have removed OnConfiguring method.

    Thursday, April 9, 2020 9:57 AM
  • User1120430333 posted

    Maybe you should try the approach that has already been mentioned.

    using System.Net;
    using DAL;
    using DAL.Models;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Diagnostics;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Serilog;
    
    namespace WebApi3.x
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
                Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                //DAL
                services.AddTransient<IDaoAuthor, DaoAuthor>();
                services.AddTransient<IDaoPayroll, DaoPayroll>();
                services.AddTransient<IDaoArticle, DaoArticle>();
    
                services.AddDbContext<PublishingCompanyContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
    
                services.AddMvc(options =>
                {
                    options.Filters.Add(new ErrorHandlingFilter(Configuration));
    
                });
    
    
                services.AddControllers();
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerfactory)
            {
                app.UseExceptionHandler(
                    options =>
                    {
                        options.Run(
                            async context =>
                            {
                                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                                context.Response.ContentType = "text/html";
                                var ex = context.Features.Get<IExceptionHandlerFeature>();
                                if (ex != null)
                                {
                                    if (ex.Error.InnerException != null)
                                    {
                                        var err = $"<h1>Error: {ex.Error.Message} </h1>{ex.Error.StackTrace } {ex.Error.InnerException.Message} ";
                                        await context.Response.WriteAsync(err).ConfigureAwait(false);
                                    }
                                    else
                                    {
                                        var err = $"<h1>Error: {ex.Error.Message} </h1>{ex.Error.StackTrace }";
                                        await context.Response.WriteAsync(err).ConfigureAwait(false);
                                    }
                                }
                            });
                    }
                );
    
                loggerfactory.AddSerilog();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllers();
                });
            }
        }
    }
    
    using Microsoft.EntityFrameworkCore;
    
    
    namespace DAL.Models
    {
        public partial class PublishingCompanyContext : DbContext
        {
            public PublishingCompanyContext(DbContextOptions<PublishingCompanyContext> options)
                : base(options)
            {
            }
    
            public virtual DbSet<Article> Article { get; set; }
            public virtual DbSet<Author> Author { get; set; }
            public virtual DbSet<Payroll> Payroll { get; set; }
    
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                if (!optionsBuilder.IsConfigured)
                {
              //      optionsBuilder.UseSqlServer(new AppConfiguration(_options).GetPublishingCompanyConn());
                }
            }
    }

    Thursday, April 9, 2020 6:16 PM
  • User-1350516731 posted

    Problem still exists after approach replacement.

    Friday, April 10, 2020 4:20 PM
  • User1120430333 posted

    Where is the EF Dbcontext in what project? Where is EF installed in what project?

    In the example code I am showing, EF is installed in the Data Access Layer, a classlib project, and the model is in the DAL too. The Startup.cs is in the WebAPI project where the DI for the connectionstring is established to be used by the EF Model Dbcontext in the DAL.

    Where did you get the initial example code you're trying to use?

    Are you sure you have all EF Core components installed in the project? My DAL project using EF has the below.

    <ItemGroup>
        <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.1" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.1" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.1" />
        <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.1">
          <PrivateAssets>all</PrivateAssets>
          <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
      </ItemGroup>

    Friday, April 10, 2020 6:30 PM
  • User-1350516731 posted

    I have created new project from mvc template and I have added all you mentioned packages. EF context and web-application stored in the same project. With OnConfiguring() it works fine but not with AddDbContext (error the same).

    Saturday, April 11, 2020 10:35 AM
  • User475983607 posted

    I have created new project from mvc template and I have added all you mentioned packages. EF context and web-application stored in the same project. With OnConfiguring() it works fine but not with AddDbContext (error the same).

    Your initial code has logical bugs.   It is not clear if you fixed these bugs.

    I provided a standard pattern used in every tutorials and VS templates for adding connection string options from configuration.    It's is not clear if you followed the recommendation.  I assume not since you are still having this rather trivial issue.

    Saturday, April 11, 2020 12:25 PM
  • User-1350516731 posted
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.HttpsPolicy;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Hosting;
    using efmvctest.Entities;
    using Microsoft.EntityFrameworkCore;
    
    namespace efmvctest
    {
        public class Startup
        {
            public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllersWithViews();
                services.AddDbContext<TotalForumContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SqlServer")));
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                
                app.UseHttpsRedirection();
                app.UseStaticFiles();
    
                app.UseRouting();
    
                app.UseAuthorization();
    
                app.UseEndpoints(endpoints =>
                {
                    endpoints.MapControllerRoute(
                        name: "default",
                        pattern: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }
    

    Saturday, April 11, 2020 7:02 PM
  • User475983607 posted

    I'm glad you followed the standard pattern and fixed this issue.

    Saturday, April 11, 2020 7:43 PM
  • User-1350516731 posted
      public string Index()
            {
                Account temp;
                using(var context = new efmvctestContext())
                  temp = context.Account.First();
                return temp.Nick;
            }

    in HomeController.

    InvalidOperationException: 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<TContext> object in its constructor and passes it to the base constructor for DbContext.

    • Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)

    • Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()

    • Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()

    • Microsoft.EntityFrameworkCore.DbContext.get_Model()

    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityType()

    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.CheckState()

    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.get_EntityQueryable()

    • Microsoft.EntityFrameworkCore.Internal.InternalDbSet<TEntity>.System.Linq.IQueryable.get_Provider()

    • System.Linq.Queryable.First<TSource>(IQueryable<TSource> source)

    • efmvctest.Controllers.HomeController.Index() in HomeController.cs

    • <div class="source">
      1. temp = context.Account.First();
      </div>
    • lambda_method(Closure , object , object[] )

    • Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(object target, object[] parameters)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()

    • Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, object state, bool isCompleted)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)

    • Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()

    • Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)

    • Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)

    • Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)

    • Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

    use master
    IF (EXISTS(SELECT TOP 1 1 FROM sys.sql_logins WHERE [name] = 'adminuser'))
        DROP LOGIN adminuser;
    go
    drop database if exists efmvctest
    go
    create database efmvctest
    EXEC sp_configure 'CONTAINED DATABASE AUTHENTICATION', 1
    GO
    RECONFIGURE
    GO
    USE [master]
    GO
    ALTER DATABASE efmvctest SET CONTAINMENT = PARTIAL
    GO
    use efmvctest
    drop table if exists Account;
    drop user if exists adminuser;
    create login adminuser with password = 'Adminpassword1';
    go
    create user adminuser for login adminuser;
    grant all to adminuser;
    exec sp_addrolemember 'db_owner', 'adminuser'
    go
    create table Account
    (
    Nick NVARCHAR(MAX)
    );
    go
    insert into Account values ('asdffadsasdf');

    It's my simple db. Then, I am creating context using "dotnet ef dbcontext scaffold "Server=localhost;Database=efmvctest;User ID=adminuser; Password=Adminpassword1" Microsoft.EntityFrameworkCore.SqlServer -o Entities -f -v -d"

    public Startup(IConfiguration configuration)
            {
                Configuration = configuration;
            }
    
            public IConfiguration Configuration { get; }
    
            // This method gets called by the runtime. Use this method to add services to the container.
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddControllersWithViews();
                services.AddDbContext<efmvctestContext>(options 
                => options.UseSqlServer(Configuration.GetConnectionString("SqlServer")));
            }
    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft": "Warning",
          "Microsoft.Hosting.Lifetime": "Information"
        }
      },
      
        "ConnectionStrings": {
          "SqlServer": "Server=localhost; Database=efmvctest; User ID=adminuser; Password=Adminpassword1"
        }
      
    }
    

    I get correct string in browser when I'm using OnConfiguring. But with AddDbContext problem still exists. Any additions?

    Saturday, April 11, 2020 8:00 PM
  • User475983607 posted

    You did not pass the connection string option to the context. 

    But, ASP.NET Core uses constructor dependency injection.   This concept is covered in every ASP.NET Core getting started tutorial and the Core SDK project templates have sample code that illustrate the same.  The pattern has the following format.

        public class HomeController : Controller
        {
    
            private readonly efmvctestContext _db;
            public HomeController(efmvctestContext db)
            {
                _db = db;
            }

    Once properly configured you can use the content in all the Actions methods.

            [HttpGet]
            public IActionResult Index()
            {
               var results = _db.Person.Where(p => p.BusinessEntityId == 1);
               return View(results);
            }

    I recommend going through the Getting Started tutorials in this site which covers these basic constructs.

    https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/?view=aspnetcore-3.1

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, April 11, 2020 8:32 PM
  • User-1350516731 posted

    Thank you very much. Now it's working fine.

    Saturday, April 11, 2020 8:44 PM