Travus Gonzalez
Travus Gonzalez

Reputation: 89

Connection String DI in ASP.NET Core

I am not sure what I am doing wrong here, I want to use the connection string from appsettings.json and use DI to setup my DbContext for use.

{
  "ConnectionStrings": {
    "DarkwinterDatabase": "server=localhost;userid=user;pwd=pass;port=3306;database=Darkwinter;sslmode=none;"
  },
  ...
}

In the ConfigureServices method in Startup.cs I have the following code.

services.AddDbContext<PostContext>(options =>
    options.UseMySQL(Configuration.GetConnectionString("DarkwinterDatabase")));

My DbContext has one DbSet and accepts DbContextOptions to pass to base to be initialized. This is where I think I am wrong but should DI pass options to this class?

public class PostContext : DbContext
{
    public PostContext(DbContextOptions options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

How ever when I try to use my Context I get an error: There is no argument given that corresponds to the required formal parameter 'options' of 'PostContext.PostContext(DbContextOptions)

using(var db = new PostContext())
{
    var posts = db.Post.ToList();
    return View(posts);
}

This makes sense since I didn't pass one in but I thought that the service should do that? I know I am thinking about this the wrong way and was hoping someone would take the time to explain it to me.

Upvotes: 0

Views: 3169

Answers (2)

user1447718
user1447718

Reputation: 681

can you try this in your startup.cs file

services.AddDbContext<PostContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DarkwinterDatabase")));

Upvotes: 0

Philip P.
Philip P.

Reputation: 1212

You are thinking the right way. However, there are a couple of issues.

Let me explain: according to the Dependency Injection documentation the AddDbContext is a registered extension method for .NET Core Dependency Injection, that is right.

What's more important is to understand what you are injecting. It's actually very easy: with AddDbContext<PostContext> you are telling the DI framework "inject the PostContext as the application Db context everywhere where it's needed".

Now let's check what you have in PostContext (that's where you want stuff injected into):

public PostContext(DbContextOptions options)

You are trying to use constructor injection, that's a great start. You are also expecting DbContextOptions to be injected. However, the DI framework has no idea what to inject for DbContextOptions - you only told it about ApplicationDbContext and it does not know which one to inject (you might have registered a bazillion of different contexts).

You can change it to ApplicationDbContext (otherwise everything written below makes zero sense):

AddDbContext<ApplicationDbContext>(//...)

Now, your original DbContext service definition is done properly but it's still not working. There are good news for you though: you are not the only one who was shockazzeled by this behavior: "I'm registering an ApplicationDbContext and then asking for DbContextOptions and I really expect for the magic to happen" (ref. Entity Framework Issue #4558).

I have never actually tried this but according to the Entity Framework Issue #4668 the DbContextOptions<TContext> was added to the application's service provider. Now, you probably already guessed the trick to try: make the constructor ask for DbContextOptions<TContext> (if you have changed your registration to use ApplicationDbContext instead of PostContext), like this:

public class PostContext : DbContext
{
    public PostContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

Or like this if you have decided to stay with AddDbContext<PostContext>:

public class PostContext : DbContext
{
    public PostContext(DbContextOptions<PostContext> options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

Again, not sure if it will work, never tried it. If it doesn't - well, you'll have to implement a context options factory and inject it instead...

Upvotes: 2

Related Questions