System.Data.SqlClient.SqlConnection 使用不完整的 ConnectionString 在 Open() 方法中产生意外结果
System.Data.SqlClient.SqlConnection unexpected result in Open() Method with incomplete ConnectionString
在传递了不完整连接字符串的 SqlConnection
实例上调用 Open()
方法时,该方法不会引发异常。
我创建了以下示例来展示我的问题。
var success = true;
var connectionStrings = new[]
{
"Integrated Security=SSPI;",
"Initial Catalog=awdemo;Integrated Security=SSPI;",
"Data Source=.\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI;"
};
foreach (var connectionString in connectionStrings)
{
var conn = new SqlConnection(connectionString);
try
{
conn.Open();
}
catch (Exception)
{
success = false;
}
finally
{
conn.Close();
Console.WriteLine($"{connectionString} - Success = {success}");
}
}
结果:
Integrated Security=SSPI; - Success = True
Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
Data Source=.\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
我希望 conn.Open()
为前两个连接字符串抛出异常,因为它们都不完整且无效。
为什么没有抛出异常?
编辑:正如史蒂夫在评论中指出的那样,不会抛出异常,因为组件在不提供服务器信息时连接到我的 SQL 服务器的默认实例。
有没有办法强制 SqlConnection
组件对不完整的连接字符串抛出错误?在应用程序中,可以并允许创建不完整的连接字符串。
没有实际的方法可以完全验证这一点。您可能有一个连接字符串,其中包含您期望的所有组件,包括有效的服务器和数据库名称,但它是错误的服务器或错误的数据库。
因此,如果期望 class 应该在连接字符串不正确(不是无效,而是不正确)时在 conn.Open()
上失败,则您无法完全实现。
重要吗?想象几个场景,所有场景都包含不正确的连接字符串:
- 连接字符串是 "blarg!",因此尝试打开连接会引发异常。
- 连接字符串不包含服务器或数据库名称。您可以打开连接,但是当您尝试执行某些命令时它会失败。
- 连接字符串包含服务器和数据库名称,但它是错误的服务器或数据库。它失败的原因与 2.
相同
在每种情况下,您要做的第一件事是什么?您将查看异常。无论哪一行抛出它,您都会很快推断出您的连接字符串有误。
所以 "validation" 在您打开它之前无法实际验证连接字符串只是为了增加工作量。如果连接字符串错误,那确实是一个 "exceptional" 条件,因此最好让代码在它确实抛出异常的地方抛出异常。你会很快找到问题的。
除此之外,假设您真的想在尝试打开连接之前确保连接包含服务器名称和数据库名称。你可以像这样写一个扩展方法:
// Maybe give it a better name.
public static void ValidateThatConnectionHasDataSourceAndDatabase(this SqlConnection connection)
{
if (string.IsNullOrEmpty(connection.DataSource))
throw new Exception("The connection has no datasource");
if (string.IsNullOrEmpty(connection.Database))
throw new Exception("The connection has no database");
}
在创建连接之后和打开它之前,请调用 conn.ValidateThatConnectionHasDataSourceAndDatabase();
在传递了不完整连接字符串的 SqlConnection
实例上调用 Open()
方法时,该方法不会引发异常。
我创建了以下示例来展示我的问题。
var success = true;
var connectionStrings = new[]
{
"Integrated Security=SSPI;",
"Initial Catalog=awdemo;Integrated Security=SSPI;",
"Data Source=.\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI;"
};
foreach (var connectionString in connectionStrings)
{
var conn = new SqlConnection(connectionString);
try
{
conn.Open();
}
catch (Exception)
{
success = false;
}
finally
{
conn.Close();
Console.WriteLine($"{connectionString} - Success = {success}");
}
}
结果:
Integrated Security=SSPI; - Success = True
Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
Data Source=.\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
我希望 conn.Open()
为前两个连接字符串抛出异常,因为它们都不完整且无效。
为什么没有抛出异常?
编辑:正如史蒂夫在评论中指出的那样,不会抛出异常,因为组件在不提供服务器信息时连接到我的 SQL 服务器的默认实例。
有没有办法强制 SqlConnection
组件对不完整的连接字符串抛出错误?在应用程序中,可以并允许创建不完整的连接字符串。
没有实际的方法可以完全验证这一点。您可能有一个连接字符串,其中包含您期望的所有组件,包括有效的服务器和数据库名称,但它是错误的服务器或错误的数据库。
因此,如果期望 class 应该在连接字符串不正确(不是无效,而是不正确)时在 conn.Open()
上失败,则您无法完全实现。
重要吗?想象几个场景,所有场景都包含不正确的连接字符串:
- 连接字符串是 "blarg!",因此尝试打开连接会引发异常。
- 连接字符串不包含服务器或数据库名称。您可以打开连接,但是当您尝试执行某些命令时它会失败。
- 连接字符串包含服务器和数据库名称,但它是错误的服务器或数据库。它失败的原因与 2. 相同
在每种情况下,您要做的第一件事是什么?您将查看异常。无论哪一行抛出它,您都会很快推断出您的连接字符串有误。
所以 "validation" 在您打开它之前无法实际验证连接字符串只是为了增加工作量。如果连接字符串错误,那确实是一个 "exceptional" 条件,因此最好让代码在它确实抛出异常的地方抛出异常。你会很快找到问题的。
除此之外,假设您真的想在尝试打开连接之前确保连接包含服务器名称和数据库名称。你可以像这样写一个扩展方法:
// Maybe give it a better name.
public static void ValidateThatConnectionHasDataSourceAndDatabase(this SqlConnection connection)
{
if (string.IsNullOrEmpty(connection.DataSource))
throw new Exception("The connection has no datasource");
if (string.IsNullOrEmpty(connection.Database))
throw new Exception("The connection has no database");
}
在创建连接之后和打开它之前,请调用 conn.ValidateThatConnectionHasDataSourceAndDatabase();