是否可以更改app.config文件中的连接字符串并使Entity Framework开始使用新值?
我有一个多线程应用程序,其中一个线程充当调度程序。该线程可以接收一条消息,告诉它更改全部或部分连接字符串数据(例如更改密码)。然后,它将更新配置文件以包括新的连接信息,并清除所有合并的数据库连接。这部分都正常工作。
问题是,当调度程序启动新线程并且此线程创建新数据库上下文时,将使用旧的连接字符串值创建数据库连接。看来Entity Framework会将此信息的缓存副本保存在某个地方。如果我完全关闭并重新启动该应用程序,则它可以正常运行,因为显然,它必须从配置文件中读取新值。
我看到了其他建议的解决方案,其中包括将连接字符串保留为变量并将其传递给上下文构造函数。但是,由于调度程序线程不了解它创建的“作业”线程的内部知识(有些甚至可能不需要数据库访问权限),这对我来说真的行不通。至少并非没有很多代码更改和工作界面的特殊要求。
这是我用来更新文件的代码。如我所说,这部分正在工作。我还需要做些其他事情来告知Entity Framework更改吗?
// Create new connection string
SqlConnectionStringBuilder connectionBuilder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings[CONNECTION_STRING_NAME].ConnectionString);
connectionBuilder.DataSource = server;
connectionBuilder.InitialCatalog = database;
connectionBuilder.UserID = user;
connectionBuilder.Password = password;
// Update connection string within config file
Configuration config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
ConnectionStringsSection section = (ConnectionStringsSection)config.GetSection("connectionStrings");
section.ConnectionStrings[CONNECTION_STRING_NAME].ConnectionString = connectionBuilder.ToString();
// Save changes
ConfigurationManager.RefreshSection("connectionStrings");
config.Save();
答案 0 :(得分:1)
ConfigurationManager.RefreshSection
方法的文档确实说过(强调是我的):
刷新命名的区域,以便下次检索该区域时,将从磁盘重新读取该区域。
问题在于EF6将ConfigurationManager.ConnectionStrings
缓存在内部类的静态属性中,因此它永远不会刷新。
不幸的是,没有刷新它的“官方”方法。以下是使用反射的暴力破解,因此使用风险自负:
static readonly Type EF6AppConfigType = typeof(DbContext).Assembly.GetType("System.Data.Entity.Internal.AppConfig");
static readonly PropertyInfo EF6DefaultAppConfig = EF6AppConfigType.GetProperty("DefaultInstance", BindingFlags.Public | BindingFlags.Static);
static readonly FieldInfo EF6ConnectionStrings = EF6AppConfigType.GetField("_connectionStrings", BindingFlags.NonPublic | BindingFlags.Instance);
static void RefreshEF6ConnectionStrings()
{
EF6ConnectionStrings.SetValue(
EF6DefaultAppConfig.GetValue(null),
ConfigurationManager.ConnectionStrings
);
}
仅在保存更改后调用它:
config.Save();
RefreshEF6ConnectionStrings();