实体框架核心1.0连接字符串

时间:2016-08-16 18:49:06

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

我们正在研究各种大型ASP.NET Core MVC 1.0应用程序。我们的每个应用程序有4层,如下所示:

  1. DTO
  2. 存储库(实体框架 - 代码优先)
  3. 服务(业务逻辑)
  4. MVC(UI-MVC)
  5. 目前,在处理所有数据库操作的存储库中,我们对DbContext中的数据库连接字符串进行了硬编码,如下所示:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    
        optionsBuilder.UseSqlServer("Data Source=somedatabase.database.windows.net;Initial Catalog=database;Integrated Security=False;User ID=username;Password=password;Connect Timeout=60;Encrypt=True;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true");
    
    }
    

    此项目作为独立的ASP.NET Core 1.0项目位于MVC项目之外。它还有一个空的Program.cs文件,它似乎是执行代码到数据库命令行所必需的(dotnet ef migrations add和dotnet ef database update)。

    我们在DbConext中有一个硬编码连接字符串的原因是因为当我们使用下面的代码时,在执行dotnet ef命令时,我们得到一个对象引用未设置为对象异常的实例。

      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
    
        optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["StandardDatabase"].ConnectionString);
    
      }
    

    但是,由于我们有一个Program.cs,如果我们为连接字符串添加Debug.WriteLine并运行项目,它会返回正确的连接字符串,如果我们在appsettings.json文件中设置连接字符串UI,UI也将成功连接。

    问题: 上面提到的堆栈是我们用于几个“Micro Apps”的,这意味着我们有几个连接到多个数据库的项目。我们还希望利用Development,Staging和Production连接字符串。

    如果我们使用Configuration Manager连接字符串,一切都适合日常操作;但是,当我们想要将Entity Frameworks代码用于数据库命令行时,我们需要进入我们想要更新的每个存储库,并将DbContext更改为硬编码连接字符串,执行命令,然后将它们更改回完成时,这变得非常麻烦。

    问题: 我们只是做错了吗?是否有一种首选实践来设置Entity Framework Core 1.0堆栈,这样我们就不必手动更改DbContext但是可以全面利用配置文件?

    任何方向都会受到赞赏!

3 个答案:

答案 0 :(得分:16)

EF Core旨在通过依赖注入进行配置。依赖注入使您的DbContext保持干净,并且与环境的实现细节无关。

您的硬编码连接字符串的初始解决方案将DbContext紧密耦合到数据库所在位置的知识。这显然是一个问题。但是您提出的解决方案将DbContext与特定配置文件的知识紧密结合在一起。那也是一个问题。

要使DbContext独立于环境细节,请创建一个带有DbContextOptions参数并调用基类构造函数的构造函数。

public class MyContext : DbContext
{
    public MyContext(DbContextOptions options) :
        base(options)
    {
    }
}

执行此操作而不是覆盖OnConfiguring。然后在主机应用程序的Startup.cs中初始化它。这就是配置文件的知识所在。

public class Startup
{
    private IConfigurationRoot _configuration;

    public Startup(IHostingEnvironment env)
    {
        _configuration = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json")
            .Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConfigurationRoot>(_configuration);

        services.AddDbContext<MyContext>(options => options
            .UseSqlServer(_configuration.GetConnectionString("MyContext")));
    }
}

现在你可以在任何地方使用你的DbContext。

答案 1 :(得分:10)

答案:我实际上比实际情况要困难得多。我跟着Juunas&#39;建议并在我的Repository DbContext类中添加以下代码:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
{

  // get the configuration from the app settings
  var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();

  // define the database to use
  optionsBuilder.UseSqlServer(config.GetConnectionString("StandardDatabase"));

}

这与dotnet ef命令行工具完美配合,而且我的MVC UI在我的startup.cs中坚持使用以下默认代码的多环境设置也很好。

var builder = new ConfigurationBuilder()
      .SetBasePath(env.ContentRootPath)
      .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
      .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
      .AddJsonFile("project.json", optional: true, reloadOnChange: true);

答案 2 :(得分:2)

IDbContextFactory也可能有所帮助。 EF命令行工具和DI可以使用此工厂来创建DBContext的实例。设计时服务(例如迁移)将发现此接口的实现与派生上下文在同一程序集中。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace MyProject
{
    public class BloggingContextFactory : IDbContextFactory<BloggingContext>
    {
        public BloggingContext Create()
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Filename=./blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}