之前
public DbConnection GetConnection(String connectionName)
{
ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
DbConnection conn = factory.CreateConnection();
conn.ConnectionString = cs.ConnectionString;
conn.Open();
return conn;
}
然后我开始查看.NET框架文档,看看各种事物的记录行为是什么,并尝试处理它们。
例如:
ConfigurationManager.ConnectionStrings...
文档说明称,如果无法检索到集合,则调用 ConnectionStrings 会抛出 ConfigurationErrorException。在这种情况下,我无法处理此异常,因此我将让它发生。
下一部分是实际索引
ConnectionStrings
以查找connectionName:...ConnectionStrings[connectionName];
在这种情况下,ConnectionStrings文档中说,如果找不到连接名称,则该属性将返回null。我可以检查是否发生了这种情况,并抛出异常,让高层知道他们提供了无效的connectionName。
ConnectionStringSettings cs=
ConfigurationManager.ConnectionStrings[connectionName];
if (cs == null)
throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
我重复相同的练习,使用:
DbProviderFactory factory =
DbProviderFactories.GetFactory(cs.ProviderName);
“
GetFactory”方法没有记录,如果找不到指定“ProviderName”的工厂会发生什么。虽然它没有记录返回null
,但我仍然可以防御性地进行检查以获取null:
DbProviderFactory factory =
DbProviderFactories.GetFactory(cs.ProviderName);
if (factory == null)
throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");
接下来是构建DbConnection对象:
DbConnection conn = factory.CreateConnection()
再次,文档没有说明如果无法创建连接会发生什么,但我可以检查返回的对象是否为空值:
DbConnection conn = factory.CreateConnection()
if (conn == null)
throw new Exception.Create("Connection factory did not return a connection object");
接下来是设置Connection对象属性:
conn.ConnectionString = cs.ConnectionString;
这段话的意思是:文档没有说明如果无法设置连接字符串会发生什么。会抛出异常吗?还是忽略它?像大多数异常一样,如果在尝试设置连接的 ConnectionString 时出现错误,我无法恢复。所以我什么也不做。
最后,打开数据库连接:
conn.Open();
DbConnection的Open方法是抽象的,因此取决于从DbConnection派生的任何提供程序来决定它们抛出什么异常。在抽象的Open方法文档中也没有关于如果发生错误会发生什么的指导。如果连接时出现错误,我知道我无法处理它 - 我必须让它上升到调用方,让其向用户显示一些UI,并让他们重试。
之后
public DbConnection GetConnection(String connectionName)
{
//Get the connection string info from web.config
ConnectionStringSettings cs= ConfigurationManager.ConnectionStrings[connectionName];
//documented to return null if it couldn't be found
if (cs == null)
throw new ArgumentException("Could not find connection string \""+connectionName+"\"");
//Get the factory for the given provider (e.g. "System.Data.SqlClient")
DbProviderFactory factory = DbProviderFactories.GetFactory(cs.ProviderName);
//Undefined behaviour if GetFactory couldn't find a provider.
//Defensive test for null factory anyway
if (factory == null)
throw new Exception("Could not obtain factory for provider \""+cs.ProviderName+"\"");
//Have the factory give us the right connection object
DbConnection conn = factory.CreateConnection();
//Undefined behaviour if CreateConnection failed
//Defensive test for null connection anyway
if (conn == null)
throw new Exception("Could not obtain connection from factory");
//Knowing the connection string, open the connection
conn.ConnectionString = cs.ConnectionString;
conn.Open()
return conn;
}
摘要
所以我的四行代码函数变成了12行,并需要查找5分钟的文档。最终,我确实发现了一种情况,即某个方法允许返回null值。但在实践中,我只是将访问违规异常(如果尝试调用null引用上的方法)转换为InvalidArgumentException。
我还捕获了两种可能存在null返回对象的情况;但同样,我只是将一个异常替换为另一个异常。
积极的一面是,它确实发现了两个问题,并解释了异常消息中发生了什么,而不是在后面出现问题(即责任到此为止)。
但这值得吗?这是否过度防御式编程?