我不确定我在这里做错了什么,我想使用appsettings.json中的连接字符串并使用DI设置我的DbContext以供使用。
{
"ConnectionStrings": {
"DarkwinterDatabase": "server=localhost;userid=user;pwd=pass;port=3306;database=Darkwinter;sslmode=none;"
},
...
}
在Startup.cs的ConfigureServices方法中,我有以下代码。
services.AddDbContext<PostContext>(options =>
options.UseMySQL(Configuration.GetConnectionString("DarkwinterDatabase")));
我的DbContext有一个DbSet并接受DbContextOptions传递给base进行初始化。这是我认为我错了,但DI应该将选项传递给这个类吗?
public class PostContext : DbContext
{
public PostContext(DbContextOptions options) : base(options) { }
public DbSet<Post> Post { get; set; }
}
当我尝试使用我的上下文时,我得到一个错误:没有任何参数符合所需的形式参数&#39; options&#39; &#39; PostContext.PostContext(DbContextOptions)
using(var db = new PostContext())
{
var posts = db.Post.ToList();
return View(posts);
}
这是有道理的,因为我没有通过,但我认为服务应该这样做?我知道我正在以错误的方式思考这个问题,并希望有人会花时间向我解释。
答案 0 :(得分:2)
你正在思考正确的方法。但是,有几个问题。
让我解释一下:根据Dependency Injection documentation,AddDbContext
是.NET核心依赖注入的注册扩展方法,这是正确的。
更重要的是要了解你注射的是什么。这实际上非常简单:使用AddDbContext<PostContext>
,您正在告诉DI框架“将PostContext作为应用程序Db上下文注入所需的任何地方”。
现在让我们检查PostContext
中你有什么(这就是你希望注入的东西到):
public PostContext(DbContextOptions options)
您正在尝试使用构造函数注入,这是一个很好的开始。您还期望注入DbContextOptions
。但是,DI框架不知道要为DbContextOptions注入什么 - 你只告诉它ApplicationDbContext
并且它不知道要注入哪一个(你可能注册了大量不同的上下文 )。
你可以将它改为ApplicationDbContext
(否则下面写的所有内容都没有意义):
AddDbContext<ApplicationDbContext>(//...)
现在,您的原始DbContext服务定义已正确完成但仍无法正常工作。但是有一些好消息:你并不是唯一一个被这种行为 shockazzeled 的人:“我正在注册一个ApplicationDbContext,然后要求DbContextOptions,我真的期待着魔术发生“(参考Entity Framework Issue #4558)。
我从未尝试过这个,但根据Entity Framework Issue #4668 DbContextOptions<TContext>
已添加到应用程序的服务提供商。现在,您可能已经猜到了尝试的诀窍:让构造函数询问DbContextOptions<TContext>
(如果您已将注册更改为使用ApplicationDbContext
而不是PostContext
),如下所示:
public class PostContext : DbContext
{
public PostContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
public DbSet<Post> Post { get; set; }
}
或者像这样,如果您决定留在AddDbContext<PostContext>
:
public class PostContext : DbContext
{
public PostContext(DbContextOptions<PostContext> options) : base(options) { }
public DbSet<Post> Post { get; set; }
}
再次,不确定它是否会起作用,从未尝试过。如果没有 - 那么,你将不得不实现一个上下文选项工厂并注入它......
答案 1 :(得分:0)
你可以在startup.cs文件中试试吗
services.AddDbContext<PostContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DarkwinterDatabase")));