简体   繁体   English

ASP.NET Core中的连接字符串DI

[英]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. 我不确定我在做什么错,我想使用来自appsettings.json的连接字符串,并使用DI设置要使用的DbContext。

{
  "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. 在Startup.cs的ConfigureServices方法中,我有以下代码。

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

My DbContext has one DbSet and accepts DbContextOptions to pass to base to be initialized. 我的DbContext有一个DbSet并接受DbContextOptions传递给要初始化的基数。 This is where I think I am wrong but should DI pass options to this class? 这是我认为我错了的地方,但是DI应该为该类传递选项吗?

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) 但是,当我尝试使用Context时却遇到错误:没有给出与“ PostContext.PostContext(DbContextOptions)”的必需形式参数“ options”相对应的参数

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. 我知道我在想这是错误的方式,希望有人花时间向我解释。

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. 让我解释一下:根据Dependency Injection文档AddDbContext是.NET Core Dependency Injection的注册扩展方法,没错。

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 ". 这实际上非常容易:使用AddDbContext<PostContext>告诉DI框架“ 将PostContext作为应用程序Db上下文注入到需要的任何地方 ”。

Now let's check what you have in PostContext (that's where you want stuff injected into ): 现在,让我们检查你有什么PostContext (这就是你想要的东西注入 ):

public PostContext(DbContextOptions options)

You are trying to use constructor injection, that's a great start. 您正在尝试使用构造函数注入,这是一个很好的开始。 You are also expecting DbContextOptions to be injected. 您还期望注入DbContextOptions 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 ). 但是,DI框架不知道为DbContextOptions注入什么内容-您仅向它介绍了ApplicationDbContext并且它不知道要注入哪个( 您可能已经注册了成千上万个不同的上下文 )。

You can change it to ApplicationDbContext (otherwise everything written below makes zero sense): 您可以将其更改为ApplicationDbContext (否则,下面编写的所有内容都为零):

AddDbContext<ApplicationDbContext>(//...)

Now, your original DbContext service definition is done properly but it's still not working. 现在,您原始的DbContext服务定义已正确完成,但仍无法正常工作。 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 ). 不过,对于您来说,有个好消息:您不是唯一一个对此行为感到震惊的人:“ 我正在注册ApplicationDbContext,然后要求DbContextOptions,我真的希望魔术能够发生 ”(参考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. 我从未真正尝试过此操作,但是根据Entity Framework Issue#4668,DbContextOptions<TContext>添加到了应用程序的服务提供程序中。 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: 现在,您可能已经猜到了要尝试的技巧:让构造函数询问DbContextOptions<TContext> (如果您已将注册更改为使用ApplicationDbContext而不是PostContext ),如下所示:

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> : 如果您决定继续使用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... 如果不是,那么,您必须实现一个上下文选项工厂,然后注入它...

您可以在startup.cs文件中尝试一下吗

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM