0

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.

1
  • What is the DI engine that you use? Where do you config your DI to know about an object of DbContextOptions type? Commented Mar 25, 2017 at 5:37

2 Answers 2

2

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...

Sign up to request clarification or add additional context in comments.

1 Comment

Unfortunately this didn't work for me, but your answer was very insightful and I learned a lot. I am still playing around with the DI and trying different things but in the mean time I have hard coded my conn string to continue developing my blog. Thanks again for your help.
0

can you try this in your startup.cs file

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.