[英]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.