如何避免自定义ConfigurationBuilder影响XSD设计器?
我实现了一个自定义ConfigurationBuilder,根据当前环境配置修改数据库连接字符串,但没想到这个本应只影响运行时的逻辑,居然也会影响Dataset设计器,这不符合预期。
我的核心需求是:在XSD设计器中添加或修改查询、架构时,始终使用固定的连接字符串。目前遇到的问题是,只要在开发/测试环境下修改或添加TableAdapter,生成代码里的数据库前缀(比如DbObjectName和DataSourceName)会跟着当前连接字符串配置改变,示例如下:
<DbSource ConnectionRef="DefaultConnection (Web.config)" DbObjectName="TESTDB.dbo.MyTable" DbObjectType="Table" GenerateShortCommands="true" GenerateMethods="Both" ... > ... <Parameters> <Parameter AllowDbNull="true" AutogeneratedName="Weight" ColumnName="Weight" DataSourceName="TESTDB.dbo.MyTable" DataTypeServer="int" DbType="Int32" Direction="Input" ParameterName="@Weight" Precision="0" ProviderType="Int" Scale="0" Size="4" SourceColumn="Weight" SourceColumnNullMapping="false" SourceVersion="Current" /> ...
现在我每次修改数据集都得切换到生产配置、重建项目甚至重启VS2022才能避免这个问题,还怕忘了切换配置。想请教:有没有办法让XSD设计器操作TableAdapter时固定用指定连接字符串,不受自定义配置影响?或者有没有其他更合适的运行时设置连接字符串的方法?
我的自定义ConfigurationBuilder代码如下:
public class MyConnectionStringConfigurationBuilder : ConfigurationBuilder { // symbol defined in the `.csproj` file for each configuration profile #if TESTING_ENV private const string DefaultEnvironmentName = "Testing"; #else private const string DefaultEnvironmentName = "Production"; #endif public override ConfigurationSection ProcessConfigurationSection(ConfigurationSection configSection) { switch (configSection) { case ConnectionStringsSection connectionStringsSection: if(DefaultEnvironmentName == "Testing") { connectionStringsSection.ConnectionStrings["DefaultConnection"].ConnectionString = "testing connection string to test DB"; } return connectionStringsSection; default: return base.ProcessConfigurationSection(configSection); } } }
方法一:让自定义ConfigurationBuilder仅在运行时生效
XSD设计器会在设计时加载配置系统,导致你的自定义ConfigurationBuilder被执行。添加设计时环境检测,跳过连接字符串修改逻辑即可:
修改后的代码如下:
using System.ComponentModel; public class MyConnectionStringConfigurationBuilder : ConfigurationBuilder { #if TESTING_ENV private const string DefaultEnvironmentName = "Testing"; #else private const string DefaultEnvironmentName = "Production"; #endif public override ConfigurationSection ProcessConfigurationSection(ConfigurationSection configSection) { // 设计时环境直接返回原配置,不修改连接字符串 if (LicenseManager.UsageMode == LicenseUsageMode.Designtime) { return base.ProcessConfigurationSection(configSection); } switch (configSection) { case ConnectionStringsSection connectionStringsSection: if(DefaultEnvironmentName == "Testing") { connectionStringsSection.ConnectionStrings["DefaultConnection"].ConnectionString = "testing connection string to test DB"; } return connectionStringsSection; default: return base.ProcessConfigurationSection(configSection); } } }
这样设计器加载配置时不会触发连接字符串替换,只有运行时才会应用测试环境的配置。
方法二:运行时直接给TableAdapter赋值连接字符串
放弃在配置层面修改连接字符串,改为在代码运行时动态设置:
- 保持App.config/Web.config中的连接字符串为生产环境版本(供设计器使用)
- 在使用TableAdapter前,根据环境切换连接字符串:
// 示例:初始化TableAdapter时设置连接字符串 var myTableAdapter = new MyTableAdapter(); #if TESTING_ENV myTableAdapter.Connection.ConnectionString = "testing connection string to test DB"; #endif // 正常执行数据操作
这种方式彻底隔离了设计时和运行时的连接字符串,设计器始终读取配置里的生产环境字符串,不会出现数据库前缀被修改的问题。
方法三:配置多环境连接字符串,设计器固定引用
在配置文件中添加多个环境的连接字符串:
<connectionStrings> <add name="DefaultConnection_Production" connectionString="生产环境连接字符串" providerName="System.Data.SqlClient" /> <add name="DefaultConnection_Testing" connectionString="测试环境连接字符串" providerName="System.Data.SqlClient" /> </connectionStrings>
然后在XSD设计器中,将所有TableAdapter的连接引用固定为DefaultConnection_Production,运行时再根据环境切换使用测试环境的连接字符串:
// 运行时切换连接字符串 var targetConnectionString = ConfigurationManager.ConnectionStrings["DefaultConnection_Testing"].ConnectionString; myTableAdapter.Connection.ConnectionString = targetConnectionString;
这种方式既保证了设计器操作时的稳定性,又能在运行时灵活切换环境。
内容的提问来源于stack exchange,提问作者SyndRain

