缺少DbProvider吗?

时间:2019-09-05 22:20:57

标签: c# asp.net-core

C#; .NET Core 2.2; Visual Studio 2019

我的应用程序中的第一个数据库查询出现以下异常。

  

尚未为此DbContext配置数据库提供程序。可以通过重写DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。
  如果使用AddDbContext,则还请确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基本构造函数。

该方法如下:

public List<string> GetList() 
{
    try 
    {
        using (var db = new CommoditiesContext())
        {
            var list = (from commodity in db.Commodity
                        where commodity.DateObsolete.Equals(null)
                        select commodity.Name.Trim().ToUpper()).OrderBy(a => a).ToList();

            return list;
        }
    } 
    catch (Exception e) 
    {
        throw new Exception("GetList: " + e.Message);
    }
}

我通过以下方式创建了所涉及的模型

Scaffold-DbContext -Connection "Server=MyDB.company.com;Initial Catalog=THINGS;Integrated Security=True" -Context CommoditiesContext -Schemas "dbo" -Provider Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models\Commodities

CommoditiesContext.cs文件是自动生成的,并且具有以下方法:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            //warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
            optionsBuilder.UseSqlServer("Server=MyDB.company.com;Initial Catalog=THINGS;Integrated Security=True");
        }
    }

该方法似乎仅在执行以上查询时被调用。据我所知,CommoditiesContext类未实例化。

正如OnConfiguring()方法中的警告注释所述,在代码中包含连接字符串是一个坏主意。酷,我挖了。我已注释掉OnConfiguring()方法,而是尝试使用:

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

在我的startup.cs文件中。

我在本地运行Web应用程序,可以在services行上放置一个断点,并看到正确的连接字符串。我在上面的查询中中断了,但是在顶部生成了异常。

由于某种原因,查询未找到service版本。

我做了很多谷歌搜索,然后重新启用OnConfiguring()方法。看来我需要在OnConfiguring()方法中插入连接字符串。

我发现大多数解决方案都需要添加:

public class CommoditiesContext : DbContext {
    private readonly IConfiguration _config;

    public CommoditiesContext(IConfiguration config) {
        _config = config;
    }

    ...
}

然后使用:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_config.GetConnectionString("CommoditiesContext"));
        }
    }

此问题是,在调用OnConfiguring()的过程中似乎没有实例化此自动生成的类,因此_config为空。

我该怎么办?

1 个答案:

答案 0 :(得分:2)

它的设置方式,您需要注入它。 这是一个示例:

public class MyController : Controller
{
    private readonly CommoditiesContext db;

    public MyController(CommoditiesContext db)
    {
        // db is 'automatically' created and given to you.
        this.db = db;
    }

    [HttpGet]
    public IActionResult GetList()
    {
        var list = (from commodity in db.Commodity
                    where commodity.DateObsolete.Equals(null)
                    select commodity.Name.Trim().ToUpper()).OrderBy(a => a).ToList();

        return this.Ok(list);
    }
}

进一步阅读:Dependency injection in ASP.NET Core

添加:

如果您有多个数据库上下文,则可以添加多个这样的内容:

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

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

用法:

public class MyController : Controller
{
    private readonly CommoditiesContext comDb;
    private readonly AnotherDbContext anoDb

    public MyController(
              CommoditiesContext comDb,
              AnotherDbContext anoDb)
    {
        this.comDb = comDb;
        this.anoDb = anoDb;
    }
}