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

时间:2017-03-25 05:14:23

标签: c# asp.net entity-framework asp.net-core

我不确定我在这里做错了什么,我想使用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);
}

这是有道理的,因为我没有通过,但我认为服务应该这样做?我知道我正在以错误的方式思考这个问题,并希望有人会花时间向我解释。

2 个答案:

答案 0 :(得分:2)

你正在思考正确的方法。但是,有几个问题。

让我解释一下:根据Dependency Injection documentationAddDbContext是.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")));