.NET MVC:首次从数据库取连接字符串,动态更新无需重启可行吗?
嘿,你的问题我都梳理清楚了,咱们一个个来解答:
完全可行!这是很常见的动态配置场景。你可以在应用启动阶段(比如ASP.NET Framework里的Global.asax的Application_Start方法),先用一个固定的初始连接字符串(这个可以放在web.config里)连接到存储配置的数据库,读取到目标业务库的连接字符串后,把它存到内存里(比如静态类、单例对象),后续所有数据库操作直接使用内存中的这个连接字符串即可,不需要再依赖web.config。
默认情况下,是的。ASP.NET Framework会监测web.config文件的变化,一旦文件被修改(比如你的代码里调用config.Save()),就会自动回收应用池并重启应用。这也是为什么你不想用当前修改web.config的方式——因为每次更新都会导致应用重启,影响用户体验。
你当前的代码是直接修改web.config的connectionStrings节点,不管是新增还是修改现有项,都会触发应用重启。要避免重启,核心思路就是不要修改web.config文件,而是把动态的连接字符串存储在内存、缓存或者专门的配置数据库中,直接从这些地方读取使用。
先看你尝试的代码:
public ActionResult Index() { UpdateSetting("test", "123"); UpdateConnectionString("testcon", "12345"); return View(); } /// <summary> /// Updates the setting. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void UpdateSetting(string key, string value) { Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); if (config.AppSettings.Settings[key] == null) { config.AppSettings.Settings.Add(key, value); } else { config.AppSettings.Settings[key].Value = value; } config.Save(); ConfigurationManager.RefreshSection("appSettings"); } /// <summary> /// Updates the connection string. /// </summary> /// <param name="key">The key.</param> /// <param name="value">The value.</param> public void UpdateConnectionString(string key, string value) { Configuration config = WebConfigurationManager.OpenWebConfiguration("~"); if (config.ConnectionStrings.ConnectionStrings[key] == null) { config.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings(key, value)); } else { config.ConnectionStrings.ConnectionStrings[key].ConnectionString = value; } config.Save(); ConfigurationManager.RefreshSection("connectionStrings"); }
这段代码的问题就在于直接修改web.config,必然触发应用重启。下面给你两个更合适的实现方案:
方案一:内存存储 + 应用启动时加载
适合连接字符串不频繁变动的场景,应用启动时加载一次,后续一直用内存中的值:
// 定义静态类管理连接字符串 public static class ConnectionStringManager { // 存储目标业务库的连接字符串 public static string TargetDbConnection { get; private set; } // 初始化方法,在应用启动时调用 public static void Initialize() { // 从web.config读取初始配置库的连接字符串 string configDbConn = ConfigurationManager.ConnectionStrings["ConfigDatabase"].ConnectionString; using (var conn = new SqlConnection(configDbConn)) { conn.Open(); // 从配置库表中查询目标连接字符串 var cmd = new SqlCommand("SELECT ConnectionString FROM AppConfigs WHERE ConfigKey = 'TargetDbConn'", conn); TargetDbConnection = cmd.ExecuteScalar()?.ToString() ?? string.Empty; } } } // 在Global.asax的Application_Start中初始化 protected void Application_Start() { ConnectionStringManager.Initialize(); // 其他启动逻辑... } // 后续使用连接字符串的示例 public ActionResult SomeDatabaseAction() { using (var conn = new SqlConnection(ConnectionStringManager.TargetDbConnection)) { // 执行数据库操作 } return View(); }
方案二:内存缓存 + 动态刷新
如果需要在应用运行过程中更新连接字符串(无需重启),可以用MemoryCache存储,支持手动刷新或自动过期:
public static class DynamicConnectionHelper { private const string CacheKey = "TargetDbConnectionString"; private const string ConfigDbConnKey = "ConfigDatabase"; public static string GetTargetConnectionString() { var cache = MemoryCache.Default; string connString = cache[CacheKey] as string; // 缓存不存在时,从数据库加载 if (string.IsNullOrEmpty(connString)) { string configDbConn = ConfigurationManager.ConnectionStrings[ConfigDbConnKey].ConnectionString; using (var conn = new SqlConnection(configDbConn)) { conn.Open(); var cmd = new SqlCommand("SELECT ConnectionString FROM AppConfigs WHERE ConfigKey = 'TargetDbConn'", conn); connString = cmd.ExecuteScalar()?.ToString() ?? string.Empty; } // 将连接字符串存入缓存,设置1小时过期(也可设为永不过期,手动刷新) cache.Add(CacheKey, connString, DateTimeOffset.Now.AddHours(1)); } return connString; } // 手动刷新缓存的方法,调用此接口即可更新连接字符串 public static void RefreshConnectionString() { MemoryCache.Default.Remove(CacheKey); } } // 更新连接字符串的示例接口 public ActionResult UpdateConnectionString(string newConnString) { // 先把新连接字符串更新到配置数据库 string configDbConn = ConfigurationManager.ConnectionStrings[ConfigDbConnKey].ConnectionString; using (var conn = new SqlConnection(configDbConn)) { conn.Open(); var cmd = new SqlCommand("UPDATE AppConfigs SET ConnectionString = @ConnString WHERE ConfigKey = 'TargetDbConn'", conn); cmd.Parameters.AddWithValue("@ConnString", newConnString); cmd.ExecuteNonQuery(); } // 刷新缓存,下次获取时会加载新值 DynamicConnectionHelper.RefreshConnectionString(); return Json(new { success = true }); }
内容的提问来源于stack exchange,提问作者Amal Sebastian

