如何在.NET Core中读取连接字符串?

175

我想从配置文件中仅读取一个连接字符串,为此需要向我的项目添加一个名为“appsettings.json”的文件,并将其内容添加到其中:

{
"ConnectionStrings": {
  "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-

 WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
    "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
    "Default": "Debug",
    "System": "Information",
    "Microsoft": "Information"
   }
 }
}

在ASP.NET上,我使用了这个:

 var temp=ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

现在我该如何在C#中读取“DefaultConnection”并将其存储在.NET Core的字符串变量中?


1
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration - Ravi Teja
6
这太搞笑了。这个问题应该很简单,但我看到的却是一堆答案,每个都走向不同的方向。 我本以为到了2022~2023年,事情应该变得简单了!我来到这里寻找答案,结果和来时一样,一无所获 :) 谢谢微软。 - undefined
4
这太搞笑了。那个问题应该很简单,但我看到的只有大量答案,每个都分叉成不同的方向。 我以为到了2022~2023年,事情应该变得简单了!我来到这里寻找答案,却像来时一样空手而归 :) 谢谢微软。 - Albert Zakhia
15个回答

143

虽然发布的答案可以,但没有直接回答我有关读取连接字符串的问题。经过大量搜索,我找到了一种稍微简单一些的方法。

在 Startup.cs 中

public void ConfigureServices(IServiceCollection services)
{
    ...
    // Add the whole configuration object here.
    services.AddSingleton<IConfiguration>(Configuration);
}
在您的控制器中添加一个用于配置的字段,并在构造函数中为其添加一个参数。
private readonly IConfiguration configuration;

public HomeController(IConfiguration config) 
{
    configuration = config;
}

现在,在您的视图代码中,您可以像这样访问它:

connectionString = configuration.GetConnectionString("DefaultConnection");

4
不会这样做。如果您在没有实体框架的情况下工作,最好将连接工厂注册为单例,例如与 dapper 一起使用。然后,如果需要,仍可以公开 connectionString 属性,但我敢打赌,在99%的情况下不是必需的。 - Stefan Steiger
4
如何在模型中访问配置项而不是控制器? - Tanmay
6
我越读越尝试,就越发现获取连接字符串是一项重大的任务。无论我尝试什么方法,我都只能得到空值。 - MC9000
19
是的,太多计算机科学家为了输出"Hello World"而创造了巨大的高悬果。令人难以置信,这是熵的最佳体现。 - JustJohn
13
我同意@JustJohn的观点,这是不必要的过度工程。连接字符串应该很容易获取,不应该花费数小时来实现。没有必要使所有东西都抽象化并包装成工厂或其他什么东西。有些东西应该始终保持简单。 - HamsterWithPitchfork
显示剩余7条评论

122

你可以使用GetConnectionString扩展方法来实现此操作:

string conString = Microsoft
   .Extensions
   .Configuration
   .ConfigurationExtensions
   .GetConnectionString(this.Configuration, "DefaultConnection");

System.Console.WriteLine(conString);

或者使用一个结构化的类来进行依赖注入:

public class SmtpConfig
{
    public string Server { get; set; }
    public string User { get; set; }
    public string Pass { get; set; }
    public int Port { get; set; }
}

创业公司:

public IConfigurationRoot Configuration { get; }


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // http://developer.telerik.com/featured/new-configuration-model-asp-net-core/
    // services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));
    Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<SmtpConfig>(services, Configuration.GetSection("Smtp"));

然后在home-controller中:

public class HomeController : Controller
{

    public SmtpConfig SmtpConfig { get; }
    public HomeController(Microsoft.Extensions.Options.IOptions<SmtpConfig> smtpConfig)
    {
        SmtpConfig = smtpConfig.Value;
    } //Action Controller


    public IActionResult Index()
    {
        System.Console.WriteLine(SmtpConfig);
        return View();
    }

在 appsettings.json 中有以下内容:

"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
},

"Smtp": {
    "Server": "0.0.0.1",
    "User": "user@company.com",
    "Pass": "123456789",
    "Port": "25"
  }

10
Configure是一个扩展方法。它应该像这样最常用:services.Configure<SmtpConfig>(Configuration.GetSection("Smtp")); 当然,这其实和另一种方式差不多,但我认为那些不了解的人可能会开始使用未被注释的那行代码,所以最好将其删除。 ;) - James Wilkins
4
不,只需要注入。即使你编写一个静态方法,仍然需要配置。不过你可以手动读取JSON/YAML文件,但这会消除掉一些覆盖的内容,例如用户密码或其他(如来自注册表的配置)。 - Stefan Steiger
3
我遇到了一个错误:"MyClass并没有定义'Configuration'..." - Robert Smith
5
在连接字符串中,"this.Configuration" 指的是哪个配置文件。"GetConnectionString(this.Configuration, 'DefaultConnection')" 的意思是获取名为 "DefaultConnection" 的数据库连接字符串。 - MC9000
1
太棒了。关于ConnectionString的问题,应该怎么做呢? - Bisneto
显示剩余10条评论

25

更多信息请查看链接: https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-strings

JSON

    {
      "ConnectionStrings": {
        "BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
      },
    }

C# 启动文件 Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BloggingContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}

编辑:从aspnetcore 3.1开始:https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1


为什么 JSON 文件应该有 ConnectionStrings 而不是 ConnectionString?因为当我使用 ConnectionString 时,我得到了 null。 - Vijay
@Vijay 请尝试使用规定的方法;)请参阅附加链接。 - markokstate
1
这种方法在 Microsoft.Extensions.Configuration (3.1.5) 中似乎已经过时了。 - Ju66ernaut
@Ju66ernaut 我相信我的编辑应该能够使答案重新变得相关。 - markokstate

20

在 .NET Core 6 中

appsettings.json

 "ConnectionStrings": {
   "DefaultConnection": "Server=**Server Name**;Database=**DB NAME**;Trusted_Connection=True;MultipleActiveResultSets=true"
  }

程序.cs

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));

数据库上下文

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

    }

}

1
谢谢您的澄清,这非常重要 - builder.Configuration.GetConnectionString("DefaultConnection"); 在 .Net 6 sdk 中确实不同。 - JaisG
我建议不要使用MARS(多个活动结果集),因为这可能会导致许多往返到数据库的操作,这可能是一个难以诊断的性能问题。 - Eric J.

14

这是我的做法:

我在appsettings.json中添加了连接字符串。

"ConnectionStrings": {
"conStr": "Server=MYSERVER;Database=MYDB;Trusted_Connection=True;MultipleActiveResultSets=true"},

我创建了一个名为SqlHelper的类

public class SqlHelper
{
    //this field gets initialized at Startup.cs
    public static string conStr;

    public static SqlConnection GetConnection()
    {
        try
        {
            SqlConnection connection = new SqlConnection(conStr);
            return connection;
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
            throw;
        }
    }
}
我在 Startup.cs 中使用 ConfigurationExtensions.GetConnectionString 方法获取连接字符串,并将其分配给 SqlHelper.conStr。
public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
        SqlHelper.connectionString = ConfigurationExtensions.GetConnectionString(this.Configuration, "conStr");
    }
现在你只需像这样调用连接字符串即可:
SqlHelper.GetConnection();

'connectionString' 定义在哪里?SqlHelper.connectionString? - Nathan
@Nathan 看起来他把conStr重命名为connectionString,因为他互换地提到了两者。 - Rich S
简洁明了,易于理解。 - N Khan

9
我发现解决这个问题的方法是在启动时使用AddJsonFile在生成器中(它允许找到存储在appsettings.json文件中的配置),然后使用它来设置一个私有_config变量。
public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        _config = builder.Build();
    }

然后我可以将配置字符串设置如下:

var connectionString = _config.GetConnectionString("DbContextSettings:ConnectionString"); 

这是在dotnet core 1.1上的内容。


7
我如何在我的控制器中访问_config变量? - sunny
通过在Startup.cs文件的ConfigureServices方法中将其添加到DI容器中。 - Stefan Steiger

8

ASP.NET Core(在我的情况下是 3.1)为我们提供了控制器的构造函数注入,所以您只需添加以下构造函数:

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    private readonly IConfiguration m_config;

    public TestController(IConfiguration config)
    {
        m_config = config;
    }

    [HttpGet]
    public string Get()
    {
        //you can get connection string as follows
        string connectionString = m_config.GetConnectionString("Default")
    }
}

以下是 appsettings.json 的示例:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}

3
以下方法适用于想要将appsettings.json中的connectionString传递到Model或ViewModel(而非Controller)的情况。这适用于ASP.NET Core 3及以上版本。有时您可能需要将connectionString传递到Model(用于SQL查询),而不是通过控制器进行依赖注入,因此以下方法将从appsettings中获取您的connectionString:
public class NameOfYourModel
{
  static class getConnection
  {
    public static IConfigurationRoot Configuration;
    public static string GetConnectionString()
    {
      var builder = new ConfigurationBuilder()
      .SetBasePath(System.IO.Directory.GetCurrentDirectory())
      .AddJsonFile("appsettings.json");
       Configuration = builder.Build();
       var connectionString =   
    Configuration.GetConnectionString("connectionStringName");
       
       return connectionString;
     }
    }
    string connStr = getConnection.GetConnectionString().ToString(); //This   
   //line now has your connectionString which you can use. 

 //Continue the rest of your code here.
}

3
在3.1版本中已经为 "ConnectionStrings" 定义了一个部分。
System.Configuration.ConnnectionStringSettings。
定义:
  "ConnectionStrings": {
    "ConnectionString": "..."
  }

注册:

public void ConfigureServices(IServiceCollection services)
{
     services.Configure<ConnectionStringSettings>(Configuration.GetSection("ConnectionStrings"));
}

注入:

public class ObjectModelContext : DbContext, IObjectModelContext
{

     private readonly ConnectionStringSettings ConnectionStringSettings;

    ...

     public ObjectModelContext(DbContextOptions<ObjectModelContext> options, IOptions<ConnectionStringSettings> setting) : base(options)
    {
          ConnectionStringSettings = setting.Value;
    }

    ...
}

用途:

   public static void ConfigureContext(DbContextOptionsBuilder optionsBuilder, ConnectionStringSettings connectionStringSettings)
    {
        if (optionsBuilder.IsConfigured == false)
        {
            optionsBuilder.UseLazyLoadingProxies()
                          .UseSqlServer(connectionStringSettings.ConnectionString);
        }
    }

2

还有一种方法。在我的示例中,您可以看到一些业务逻辑在存储库类中,我使用依赖注入在ASP .NET MVC Core 3.1中。

这里我想获得 connectiongString 用于该业务逻辑,因为可能另一个存储库将完全访问另一个数据库。

此模式允许您在同一业务逻辑存储库中访问不同的数据库。

C#

public interface IStatsRepository
{
            IEnumerable<FederalDistrict> FederalDistricts();
}

class StatsRepository : IStatsRepository
{
   private readonly DbContextOptionsBuilder<EFCoreTestContext>
                optionsBuilder = new DbContextOptionsBuilder<EFCoreTestContext>();
   private readonly IConfigurationRoot configurationRoot;

   public StatsRepository()
   {
       IConfigurationBuilder configurationBuilder = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory)
           .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
       configurationRoot = configurationBuilder.Build();
   }

   public IEnumerable<FederalDistrict> FederalDistricts()
   {
        var conn = configurationRoot.GetConnectionString("EFCoreTestContext");
        optionsBuilder.UseSqlServer(conn);

        using (var ctx = new EFCoreTestContext(optionsBuilder.Options))
        { 
            return ctx.FederalDistricts.Include(x => x.FederalSubjects).ToList();
        }
    }
}

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "EFCoreTestContext": "Data Source=DESKTOP-GNJKL2V\\MSSQLSERVER2014;Database=Test;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接