0
votes

I want to be able to create a database context with entityframework core in my webapi project using the database first approach. When I create like this it works very well

    public class TestingContext : DbContext
        {
            public TestingContext(DbContextOptions<TestingContext> options)
                : base(options)
            {
            }

            public TestingContext()
            {
            }

            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");

            }

            public DbSet<Information> Information { get; set; }
            public DbSet<ArticleUser> ArticleUser { get; set; }

        }

I had to add the line services.AddDbContext to make it work.

     public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddCors();
            //using Dependency Injection
            services.AddSingleton<Ixxx, xxx>();

            // Add framework services.

            services.AddApplicationInsightsTelemetry(Configuration);
            services.AddDbContext<TestingContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            // Register the Swagger generator, defining one or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new Info { Title = "Articles API", Version = "v1" });
            });

        }

If I remove this method from my TestingContext

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");

    }

I get the error below.

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.

Why do I need to pass my connection string to the database in two places before it can pull my data. Please assist. I am new to the core. The two places are configure services method and the context itself.

2
Is your DbContext located in a different assembly? And do you have a project.json (VS2015) project or a csproject (VS2017)? - Tseng
No it is not located in a different assembly. I created a class within the same project. Yes I do have project.json (vs 2015) - Baba
This error typically comes, when DbContext is located in a class library rather than inside the ASP.NET Core project and when one calls dotnet ef database scaffold ... from this class library, see .NET Standard Limitations - Tseng
Remove your parameterless constructor. Optionally you can remove your OnConfiguring method. - Smit

2 Answers

0
votes

Option 1: Remove parameterized constructor and OnConfiguring. Result:

public class TestingContext : DbContext
{
    public DbSet<Information> Information { get; set; }
    public DbSet<ArticleUser> ArticleUser { get; set; }
}

Option 2: Remove parameterized constructor and options in ConfigureServices in AddDbContext Result:

In Startup.cs

services.AddDbContext<TestingContext>();

In TestingDbContext.cs

public class TestingDdContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Data Source=xxxxxx;Initial Catalog=xxxxxx;Integrated Security=False;User Id=xxxxx;Password=xxxxx;MultipleActiveResultSets=True");
    }

    public DbSet<Information> Information { get; set; }
    public DbSet<ArticleUser> ArticleUser { get; set; }
}

Option 3: A parametric constructor is needed to create factory. Example:

public class TestDdContext : DbContext
{
    public TestDdContext(DbContextOptions options) : base(options)
    {
    }

    //TODO: DbSets
}

public class TestDbContextFactory : IDbContextFactory<TestDdContext>
{
    public TestDdContext Create(DbContextFactoryOptions options)
    {
        var contextOptions = new DbContextOptionsBuilder();

        contextOptions.UseSqlServer("...");

        return new TestDdContext(contextOptions.Options);
    }
}
0
votes

If you are creating tests, do you need a backing Sql database? Would the In-memory provider not serve you better?

options.UseInMemoryDatabase("database-name");

For this reason, I'd ditch using the OnConfiguring method, and rely on passing the DbContextOptions to your constructor

Side note, you have to consider what you are testing - are you testing your code that is dependent on your DbContext, or are you testing your DbContext itself - if there is no custom logic and you are merely extending the DbContext, there may not be enough value in writing tests for it - and you're not responsible for testing EFCore itself.