如果给定的SQL连接字符串显式指定了某个参数,例如";Encrypt=...
";。我尝试使用SqlConnectionStringBuilder
解析字符串,希望ContainsKey()
能告诉我是否指定了密钥,但它不起作用:
System.Data.SqlClient.SqlConnectionStringBuilder x =
new("Data Source=.;Initial Catalog=myDb;Integrated Security=True");
bool encryptSpecified = x.ContainsKey("Encrypt"); // returns true :(
澄清
我应该澄清为什么我需要知道是否明确指定了Encrypt
参数。在当前版本的Microsoft.Data.SqlClient
中,Encrypt
的默认值为true
,但在此之前(在Sql.Data.SqlClient
中(为false
。因此,为了确保升级到Microsoft.Data.SqlClient
后应用程序的向后兼容性,我希望将Encrypt
参数设置为false
,除非用户明确为其指定值。
解决方案
[基于与@Charlieface的讨论]
// important: *not* Microsoft.Data.SqlClient.SqlConnectionStringBuilder!
System.Data.SqlClient.SqlConnectionStringBuilder scsb =
new(connectionString);
if (!scsb.Encrypted) scsb.Encrypted = false; // this will explicitly set Encrypt
connectionString = scsb.ConnectionString;
ContainsKey
基本上是无用的,因为它只是告诉您是否支持某个键,而不是字符串是否真的包含该键。如果字符串没有该键,则使用默认值。
您只需使用Encrypt
属性来告诉您值是什么。如果默认值为false
(在新版Microsoft.Data.SqlClient
中已更改为true
(,则会返回false
。
此外,这比检查字符串是否包含键更有用,因为它"告诉"您在运行时实际使用的值。
var x = new SqlConnectionStringBuilder("Data Source=.;Initial Catalog=myDb;Integrated Security=True");
Console.WriteLine(x.ContainsKey("Encrypt"));
dotnetfiddle
出于同样的原因,我遇到了同样的问题。我们在小型内部网络上安装了大量SQL Server,因此我们更倾向于保留Encrypt=false
的旧默认行为。仅仅因为微软更改了默认值,就不值得在所有这些机器上为证书烦恼。在我们拥有云托管数据库的极少数情况下,我们将在服务器上显式配置证书并设置Encrypt=true。
我不想继续使用旧的System.Data.SqlClient.SqlConnectionStringBuilder
类型(正如问题的解决方案所建议的那样(,因为我的Directory.Packages.rops文件不再允许引用System.Data.SqlClient包。
我的解决方法使用一个简单的正则表达式:
using Microsoft.Data.SqlClient;
...
SqlConnectionStringBuilder builder = new(connectionString);
Regex containsEncrypt = CreateContainsEncryptRegex();
if (!containsEncrypt.IsMatch(connectionString))
{
builder.Encrypt = false;
}
connectionString = builder.ConnectionString;
...
[GeneratedRegex(@"(?i)(^|;)s*Encrypts*=", RegexOptions.Compiled)]
private static partial Regex CreateContainsEncryptRegex();