83

I have setup .net core project and db context also. But i cant start using dbContext yet due this error-

"there is no argument given that corresponds to the required formal parameter 'options'"

Controller:

public IActionResult Index()
{
    using (var db = new BlexzWebDb())
    {

    }
    return View();
}

Dbcontext Code:

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

    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<AssignedRole> AssignedRoles { get; set; }
    
}

error picture attached. How can this issue be fixed?

pic

starball
  • 20,030
  • 7
  • 43
  • 238
john Cogdle
  • 1,423
  • 2
  • 16
  • 26
  • @Stefan code added – john Cogdle Jun 10 '18 at 21:44
  • @johnCogdle post code of you data context (BlexzWebDb) – hugo Jun 10 '18 at 21:45
  • 4
    You need to read on Dependency Injection in ASP.NET Core: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.1. What you are attempting to do is fundamentally wrong. – Camilo Terevinto Jun 10 '18 at 21:47
  • DbContext added – john Cogdle Jun 10 '18 at 21:47
  • Your constructor needs some parameters (options). Moreover, CamiloTerevinto is right, you need to setup EF Core inside your startup.cs and use dependency injection in your controller – hugo Jun 10 '18 at 21:56
  • 12
    @SOusedtobegood It is in no way fundamentally wrong. You don't know the requirements, time or money constraints, quality attributes or anything else required for the project OP is working on for that matter. It is a very valid way of doing things in the right circumstances. Using DI enables many things, true, but even Microsoft doesn't make a problem out of it: `Instance pooling can increase throughput in high-scale scenarios such as web servers by re-using DbContext instances, rather than creating new instances for each request. ` Note that there is no "u r doin it rong" in there. – Zimano Aug 13 '19 at 16:26
  • 2
    Complete agree with @Zimano - It is not fundamentally wrong. This is just an easy way to connect when you only need a single connection. What if you need to build connections dynamically, for example when you want to move away from a multi tenanted DB architecture when using asp.net web api? The way I can imagine to go forward is to not rely on dependency injection, but instead create a dbcontext object on request and dynamically point it to the user's individual database. I don't see a way to do this via DI (pre EF 5.0) – PaulG Aug 05 '20 at 04:31

4 Answers4

174

Instantiate new object of DbContext from ConnectionString

var connectionstring = "Connection string";

var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
    optionsBuilder.UseSqlServer(connectionstring);


ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options);

// Or you can also instantiate inside using

using(ApplicationDbContext dbContext = new ApplicationDbContext(optionsBuilder.Options))
{
   //...do stuff
}
Qamar Zaman
  • 2,521
  • 2
  • 10
  • 16
  • 3
    How does this answer the question? – Derek Pollard Apr 08 '19 at 16:57
  • 31
    we can instantiate DbContext like this – Qamar Zaman Apr 09 '19 at 07:55
  • 11
    @DerekPollard The OP asked how to instantiate an EF context and this answer shows how to. Since OP specifically did not understand that they had to provide a parameter to that constructor, the answerer has shown how to pass in options as well. – Zimano Aug 13 '19 at 16:20
  • 20
    This should be the correct answer. If you don't want DI, you should not be peer-pressured to do so. – neeohw Apr 20 '20 at 14:06
  • 9
    I agree with @neeohw ! This must be the correct answer. For example, I need a separate connection string for migration (in background task), with different permissions, and I don't need to implement dependencies here (and it's hard to do it) – Alexander Brattsev Jul 14 '20 at 15:40
  • now how does one dispose a context without using "using" ? – phil123456 Oct 11 '21 at 10:26
70

Note


At the time of writing the use of EF Core with the Dependency injection framework wasn't as known as it is now. This answers gives answer to the question from a DI perspective, which at the time, helped out OP.

The other answer provides you a conventional way to instantiate the DbContext using the new operator.


TL;DR, 3 options:

Option 1

Register the DbContext during application configuration:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContextPool<BlexzWebDb>(options => 
           options.UseSqlServer(Configuration.GetConnectionString("BlexzWebConnection")));
}

and use the DI framework to retrieve it:

public class SomeController : Controller
{
    private readonly BlexzWebDb _db;

    //the framework handles this
    public SomeController(BlexzWebDb db)
    {
        _db = db;
    }
}

Option 2

If you are looking for a design-time IdentityDbContext using IOptions<OperationalStoreOptions>, see: Add migration for ApiAuthorizationDbContext from another project - EF Core

Option 3

Or use the new operator and provide the details, see @Qamar Zaman's answer for details.


The long answer, and why DI is a treat

In EF Core it's common to pass some DbContextOptions to the constructor.

So in general, a constructor looks like this:

public BlexzWebDb(DbContextOptions<BlexzWebDb> options) : base(options)

As you can see there, there is no valid overload in the form of a parameter-less constructor:

Thus, this does not work:

using (var db = new BlexzWebDb())

Obviously, you can pass in an Option object in the constructor but there is an alternative. So,

Instead


.Net Core has IoC implemented in it's roots. Okay, this means; you don't create a context, you ask the framework to give you one, based on some rules you defined before.

Example: somewhere you will register your dbcontext, (Startup.cs):

//typical configuration part of .net core
public void ConfigureServices(IServiceCollection services)
{
    //some mvc 
    services.AddMvc();
  
    //hey, options! 
    services.AddDbContextPool<BlexzWebDb>(options => 
           options.UseSqlServer(Configuration.GetConnectionString("BlexzWebConnection")));
    //...etc

Now the registering part is done, you can retrieve your context from the framework. E.g.: inversion of control through a constructor in your controller:

public class SomeController : Controller
{
    private readonly BlexzWebDb _db;

    //the framework handles this
    public SomeController(BlexzWebDb db)
    {
        _db = db;
    }

    //etc.

why?

So, why not just provide the arguments and new it?

There is nothing wrong with the use of new - there are a lot of scenario's in which it works best.

But, Inversion Of Control is considered to be a good practice. When doing asp dotnet core you're likely to use it quite often because most libraries provide extension methods to use it. If you are not familiar with it, and your research allow it; you should definitely give it a try.

Therefore, instead of providing "just a way to instantiate" the object, I'll try to get you onto this track - inline with the framework. It will save you some hassle afterwards. Besides, otherwise "use an activator's CreateInstance" would just be as valid as an answer ;-)

Some links:

Stefan
  • 17,448
  • 11
  • 60
  • 79
  • 2
    Are you awesome! Thanks dude. Very nice and clean described – john Cogdle Jun 10 '18 at 22:18
  • 3
    Be aware that if you go with `.AddDbContext<>` your entire ioc tree is now exposed to ef (e.g. for things like logging, and starting with Ef 2.1 you can even inject services into models). This may or may not matter to you, but we explicitly opted out of this pattern, for example :) – zaitsman Jun 11 '18 at 01:11
  • 1
    @zaitsman: which makes me wondering; which pattern do you use then? – Stefan Aug 15 '18 at 07:51
  • @Stefan you had said "there is no valid overload in the form of a parameter-less constructor" for context class but there is a way to do like shown in answer below – hasan Sep 17 '18 at 06:12
  • Yes, it is, that why I up-voted it 2 months ago ;-) Nevertheless I am more fond to stick with the framework's defaults. – Stefan Sep 17 '18 at 07:12
  • But what if I really need to instantiate a new context - for example, I want to ensure concurrency, so I instantiate a new context for each request: `using (MyContext context = new MyContext()){}` How do I do this without the parameterless constructor? – Eutherpy Sep 19 '18 at 09:07
  • 1
    Then you can use @hasan 's answer, although it seems the actual parameter-less constructor is missing, you can add it manually. – Stefan Sep 19 '18 at 09:44
  • 1
    @Eutherpy: to *ensure* that, by the way, is one of the configuration options which are provided by the framework. I don't know the exact method call but every IoC framework has them. So, even in this case I would advise you to use the framework ;-) – Stefan Sep 19 '18 at 09:46
  • @Stefan There is no "parameterless" constructor for EF contexts. It is often confused with a parameterless constructor that calls the base `DbContext`. You cannot add a parameterless constructor without providing a parameter to the base `DbContext` constructor as you will get an exception that there is no database provider initialized. This is why you often see `public SomeDbContext() : base("name=LoggingDb")` or the like. – Zimano Aug 13 '19 at 16:18
  • @Stefan It relates to one of the comments that you made about the parameterless constructor. You seem to have deleted your latest comment where you were discussing this with me and replaced it with this new one, is there any problem that surfaced for you after 4 weeks? – Zimano Sep 10 '19 at 09:25
  • @Zimano: no, but I realized I might misread your comment on that one. So that's why I reverted it. In general: one could add a parameter-less constructor by inheritance and call the base constructor with a constant from that one. So I am still wondering about your comment. By the way: the question is how to do it right in EF core + asp.net core. That would be through the IOC framework. – Stefan Sep 10 '19 at 09:31
  • 1
    if only i found this answer few hours ago! – Harry Nov 24 '19 at 11:20
  • How do we do this with [partial views](https://stackoverflow.com/questions/66021287/using-a-di-with-partial-views-in-asp-net-core-razor-pages)? – kesarling He-Him Feb 03 '21 at 04:31
  • @d4rk4ng31: you should pass the data to the partial view, not the DB context. – Stefan Feb 03 '21 at 11:51
23

As addition of @Stefan's answer there is another way to achieve this. You can set db connection string in OnConfiguring method of DbContext class without adding DbContext service in startup.cs.

Setting.cs

public static class Setting
{
    public static string ConnectionString { get; set; }
}

Startup.cs

Setting.ConnectionString = Configuration.GetSection("ConnectionStrings:BlexzDbConnection").Value;

BlexzWebDb.cs

public class BlexzWebDb : DbContext 
{
   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
       if (!optionsBuilder.IsConfigured)
       {
           optionsBuilder.UseSqlServer(Setting.ConnectionString);
       }
    }
}

HomeController.cs

public class HomeController : Controller
{
    private readonly BlexzWebDb db;

    public HomeController()
    {
        this.db = new BlexzWebDb();
    }

    //etc.
AGuyCalledGerald
  • 7,882
  • 17
  • 73
  • 120
hasan
  • 3,484
  • 1
  • 16
  • 23
4

Code sample for EF Core 3.1:

public class Test
{
    private readonly IServiceProvider _serviceProvider;

    public Test(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public async Task<RequestResult> Handle(...)
    {
        await using var context = CreateContext();
        ...
    }

    private DocumentContext CreateContext()
    {
        var options = _serviceProvider.GetService<IOptions<DocumentContextOptions>>();
        return new DocumentContext(options);
    }
}
Sam Sch
  • 642
  • 7
  • 15