如何使用 ConfigurationManager 从 appsetting 中获取连接字符串?

Posted

技术标签:

【中文标题】如何使用 ConfigurationManager 从 appsetting 中获取连接字符串?【英文标题】:How can I get connectionstring from appsetting using ConfigurationManager? 【发布时间】:2021-11-21 14:38:49 【问题描述】:

我创建了一个包含 Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools 和 System.Configuration.ConfigurationManager 的 asp.net 核心 Web api 项目。我运行了脚手架命令Scaffold-DbContext "Data Source=DEX-LEP3LOXH0M5\\SQLEXPRESS;Initial Catalog=LibraryStore;Integrated Security=True" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models

在从脚手架 cmd 创建的 Context.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. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
                 optionsBuilder.UseSqlServer("Data Source=DEX-LEP3LOXH0M5\\SQLEXPRESS;Initial Catalog=LibraryStore;Integrated Security=True");
               
            
        

当我运行到控制器的路由路径时,它运行良好,我能够看到数据库中的记录。但是在那条#warning 消息中,它提供了一个我关注的链接。在我的 appsettings.json 文件中,我添加了ConnectionStrings


  "Logging": 
    "LogLevel": 
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    
  ,
  "AllowedHosts": "*",
  "ConnectionStrings": 
    "Default": "Data Source=DEX-LEP3LOXH0M5\\SQLEXPRESS;Initial Catalog=LibraryStore;Integrated Security=True"
  

那么我下一步就是在startup.cs的ConfigureServices中添加代码:

public void ConfigureServices(IServiceCollection services)
        

            services.AddControllers();
            services.AddSwaggerGen(c =>
            
                c.SwaggerDoc("v1", new OpenApiInfo  Title = "LibraryWebAPI", Version = "v1" );
            );
            services.AddDbContext<LibraryStoreContext>(options =>
                  options.UseSqlServer(Configuration.GetConnectionString("Default")));
        

然后它说要更改创建的 Context.cs 文件中的OnConfiguring()

我做了以下事情:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        
            if (!optionsBuilder.IsConfigured)
            
                
                optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["Default"].ConnectionString);
            
        

但随后它会在optionsBuilder 行上生成错误消息:

System.Configuration.ConnectionStringSettingsCollection.this[string].get 返回 null。

如果相同的连接字符串在遵循link to add connection to connectionstring in appsettings 之前有效,是否有返回 null 的原因?


包括我的控制器:

        [HttpGet]
        [Route("GetAllDetails")]
        public IEnumerable<LibraryInfo> GetDetails()
        
            using (var context = new LibraryStoreContext())
            
                // get all library details
                return context.LibraryDetails.ToList();
            
        

【问题讨论】:

如果您不在“上下文”类中覆盖 OnConfiguring 会发生什么?您已在 startup.cs 'ConfigureServices' 中传递了连接字符串,因此您无需再次传递它。我认为我从未在我的任何 DbContext 子类中覆盖 onconfiguring 来设置连接字符串。 当我这样做时它告诉我: S​​ystem.InvalidOperationException: '没有为此 DbContext 配置数据库提供程序。可以通过覆盖“DbContext.OnConfiguring”方法或在应用程序服务提供程序上使用“AddDbContext”来配置提供程序。如果使用了“AddDbContext”,那么还要确保您的 DbContext 类型在其构造函数中接受 DbContextOptions 对象并将其传递给 DbContext 的基本构造函数。' 你的上下文类中有这样的构造函数吗?公共 ApplicationDbContext(DbContextOptions options) : base(options) 是的,我有一个默认构造函数,我有一个重载的构造函数public LibraryStoreContext(DbContextOptions&lt;LibraryStoreContext&gt; options) : base(options) 尝试删除默认构造函数。这是 VS 在您使用内置标识创建新站点时创建的类 -> pastebin.com/eirxvS9b。它不直接基于 DbContext,但我认为这并不重要。我通常在 AddControllers 上方也有 AddDbContext。 【参考方案1】:

我只是找到了一种更舒适的方式来维护生成迁移,您不必从 Web 项目运行命令。

数据库上下文

internal class ContosoContext : DbContext

    private readonly IConfiguration configuration;
    public ContosoContext(IConfiguration configuration)
    
        this.configuration = configuration;
    
    public ContosoContext()
    
        this.configuration = null;
    
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    
        base.OnConfiguring(optionsBuilder);
        if (configuration == null)
        
            // Only used when generating migrations
            // Contoso.Data = name of the project where your migrations should reside
            var migrationsConnectionString = @"Server=(localdb)\mssqllocaldb;Database=Contoso;Trusted_Connection=True;ConnectRetryCount=0";
            optionsBuilder.UseSqlServer(migrationsConnectionString, options => options.MigrationsAssembly("Contoso.Data"));
        
        else
        
            optionsBuilder.UseSqlServer(configuration.GetConnectionString("Contoso"));
        
    

注册DbContext

services.AddDbContext<ContosoContext>(options => 
   options.UseSqlServer(Configuration.GetConnectionString("Contoso"));
);
在运行应用程序(Web 项目)时,将调用带参数的构造函数。 从Contoso.Data 文件夹(dotnet ef migrations add myawesomemigration) 生成迁移时,将调用无参数构造函数。

这消除了在生成数据库迁移期间过度指定参数的需要:

dotnet ef migrations add AddIdentity

【讨论】:

这很可靠!谢谢你和我分享这个! :)【参考方案2】:

.Net Core 应用程序使用 appsettings.json 而不是 web.config 文件。

因为 .Net Core 应用程序是自托管的并且几乎可以在任何平台上运行,它们不再需要托管在 IIS 上。 .Net Core 应用程序设置默认以 Json 格式 (appsettings.json) 存储,而 .Net Framework 应用程序配置以 XML 格式存储在 web.config 文件中 这就是为什么在使用ConfigurationManager 时它不应该与您的 appsettings.json 一起使用

根据您发送的 guid,他们说要更改 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)

但这不是在 .net 核心应用程序上说的

【讨论】:

所以ConfigurationManager 不能与asp.net core web api 项目一起使用?是否有正确的方法从带有上下文文件的 asp.net 核心 web api 项目中的 appsettings.json 读取连接字符串? 在您的DbContext 中注入IConfiguration configuration。然后您可以在DbContext.Configure 方法中调用configuration.GetConnectionString("somename"),从您的appsettings file/environment variables/command-line parameters 中获取connectionStrings:somename 值。 我这样做like this。唯一的缺点是您需要从 Web 项目生成迁移... aspsnippets.com/Articles/… 我用了这个,它成功了:) 谢谢你们的帮助!

以上是关于如何使用 ConfigurationManager 从 appsetting 中获取连接字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ConfigurationManager 通过 ClickOnce 更新持久化 app.config?

如何使用 ConfigurationManager 从 appsetting 中获取连接字符串?

如何使用ConfigurationManager读写配置文件

如何使用ConfigurationManager? (Microsoft.IdentityModel.Protocols)

如何在 Azure 的 ConfigurationManager.ConnectionStrings 上使用 ConnectionStrings 创建 EF 迁移?

如何使用 configurationManager 从 .Net 4.0 中的 App.config 读取值?