我正在尝试在ASP.NET Core 2.1 API项目中注入一个简单的连接字符串。

appsettings.json:

{
    "ConnectionStrings": {
        "DefaultConnection": "Server=xxx.database.windows.net;Database=xxx;User Id=frontend;Password=xxx;"
    }
}


Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    var connStr = Configuration.GetConnectionString("DefaultConnection");
    services.AddDbContext<DB>(options => options.UseSqlServer(connStr));


DbContext:

public class DB : DbContext
{
    public DB(DbContextOptions<DbContext> options) : base(options) { }
    public DB() { }

    public DbSet<MenuItem> MenuItemList { get; set; }
}


我的控制器:

public class MenuItemsController : ControllerBase
{
    DB _context;
    public MenuItemsController(DB context)
    {
        _context = context;
    }

    // GET api/values
    [HttpGet]
    public ActionResult<IEnumerable<string>> Get()
    {
        try
        {
            var ddd = _context.MenuItemList.ToList();
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        return new string[] { "value1", "value2" };
    }
}


我收到以下错误:


  没有为此DbContext配置数据库提供程序。


从appsettings文件中正确读取了连接字符串,我缺少什么吗?我读过其他文章,人们只是在DB上下文中配置连接部分,但我更喜欢通过注入来实现。

最佳答案

这是数据库上下文类型DB上的两个构造函数:

public DB(DbContextOptions<DbContext> options) : base(options) { }
public DB() { }


因此,当依赖项注入容器尝试解析数据库上下文时,它将查看那些构造函数,并尝试确定使用哪个构造函数来创建对象。

首先,它将查看期望DbContextOptions<DbContext>参数的对象。通常,DbContextOptions被自动注册为AddDbContext<T>()调用的一部分。但是,注册的类型是DbContextOptions(非通用)和DbContextOptions<T>

因此,对于您的情况,对于数据库上下文DB,仅注册类型DbContextOptionsDbContextOptions<DB>

因此,依赖项注入容器无法解析DbContextOptions<DbContext>,因此无法使用该构造函数。因此它将使用下一个恰好是空构造函数的构造函数。由于空的构造函数不支持任何配置,因此数据库上下文将是未配置的,并且在尝试使用它时会收到该错误。

解决方案非常简单:在该构造函数中调整DbContextOptions<>类型。您可以使用DbContextOptionsDbContextOptions<DB>。通常首选后者,因为它允许您在同一应用程序中拥有多个数据库上下文,但是如果您只有一个数据库上下文,则也可以使用前者。我还建议您删除空的构造函数,以确保不会意外使用它:

public DB(DbContextOptions<DB> options)
    : base(options)
{ }

10-04 16:57