【问题标题】:ASP.NET Core 中的连接字符串 DI
【发布时间】:2017-08-18 04:15:13
【问题描述】:

我不确定我在这里做错了什么,我想使用 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 传递给要初始化的基。这是我认为我错的地方,但 DI 应该将选项传递给这个类吗?

public class PostContext : DbContext
{
    public PostContext(DbContextOptions options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

当我尝试使用我的上下文时,我得到一个错误:没有给定的参数对应于'PostContext.PostContext(DbContextOptions)所需的形式参数'options'

using(var db = new PostContext())
{
    var posts = db.Post.ToList();
    return View(posts);
}

这是有道理的,因为我没有传递一个,但我认为服务应该这样做?我知道我想错了,希望有人能花时间向我解释。

【问题讨论】:

  • 您使用的 DI 引擎是什么?您在哪里配置您的 DI 以了解 DbContextOptions 类型的对象?

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


【解决方案1】:

你的想法是对的。但是,有几个问题。

让我解释一下:根据Dependency Injection documentationAddDbContext是.NET Core依赖注入的注册扩展方法,没错。

更重要的是了解您正在注入的内容。这实际上非常简单:使用 AddDbContext&lt;PostContext&gt; 您是在告诉 DI 框架“在需要的地方将 PostContext 作为应用程序 Db 上下文注入”。

现在让我们检查一下您在 PostContext 中的内容(这是您希望将东西注入进入的地方):

public PostContext(DbContextOptions options)

您正在尝试使用构造函数注入,这是一个很好的开始。您还期望DbContextOptions 被注入。但是,DI 框架不知道要为 DbContextOptions 注入什么 - 您只告诉它 ApplicationDbContext 并且它不知道要注入哪个(您可能已经注册了无数不同的上下文)。

你可以把它改成ApplicationDbContext(否则下面写的一切都是零意义):

AddDbContext<ApplicationDbContext>(//...)

现在,您的原始 DbContext 服务定义已正确完成,但仍无法正常工作。不过,对您来说有个好消息:您不是唯一一个被这种行为震惊的人:“我正在注册一个 ApplicationDbContext,然后请求 DbContextOptions,我真的期待魔法发生”(参考Entity Framework Issue #4558)。

我从未真正尝试过,但根据Entity Framework Issue #4668DbContextOptions&lt;TContext&gt; 已添加到应用程序的服务提供程序中。现在,您可能已经猜到了尝试的技巧:让构造函数请求DbContextOptions&lt;TContext&gt;(如果您已将注册更改为使用ApplicationDbContext 而不是PostContext),如下所示:

public class PostContext : DbContext
{
    public PostContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

如果你决定留在AddDbContext&lt;PostContext&gt;,或者像这样:

public class PostContext : DbContext
{
    public PostContext(DbContextOptions<PostContext> options) : base(options) { }
    public DbSet<Post> Post { get; set; }
}

再次,不确定它是否会起作用,从未尝试过。如果它没有 - 好吧,你将不得不实现一个上下文选项工厂并注入它......

【讨论】:

  • 不幸的是,这对我不起作用,但是您的回答非常有见地,我学到了很多东西。我仍在使用 DI 并尝试不同的东西,但同时我已经硬编码了我的 conn 字符串以继续开发我的博客。再次感谢您的帮助。
【解决方案2】:

你能在你的 startup.cs 文件中试试这个吗

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    相关资源
    最近更新 更多