你有很多东西与此代码回事。我完全重写了它,这不是最简单的代码,甚至也不是最好的代码,但它是为了说明需要了解更多或正在处理的领域。
研究异常处理,尤其是何时使用它以及如何使用它。切勿写入吞噬错误的尝试块。如果此方法返回null,你打算做什么?表名是不好的?连接失败了吗?用户可能会也可能不会修复这个错误,但是您会吞噬它。现在没有人知道它是什么。
更糟糕的是,甚至可能没有人知道在这里发生的错误取决于您对null做了什么。永远不要吞下这样的错误。应用程序应该在发生错误的地方失败。还要小心返回这样的空值。当您返回空值,然后执行其他操作时,应用程序可能会在某个地方出现故障,而原始错误现在很难找到并修复。编写框架时,您可能偶尔会以这种风格返回空值。对于普通的应用程序,通常不需要它,几乎也不是一个好主意。
良好质量的生产代码通常只包含很少的异常处理,因为您应该使用条件来处理任何您可以预见的事情。任何你无法预见的东西通常也无法处理。你可能有很多尝试...... finally块存在清理资源,但一个应用程序应该包含很少的实际try..catch黑色。通常,您会让错误传播回调用堆栈,最终处理程序在应用程序关闭之前通知用户。
以下仍然不是您可以编写的最佳代码。我保持原来的合理性,并删除了一些快捷方式,使其更清晰。研究差异,并从那里去
public class SomeClass
{
//Use parameters rather than accessing module level properties
private IList<ColumnInformation> GetColumnInformationForTable(string dbName, string tableName)
{
// Favor object oriented styles and meaningful names. Your method does not return a list of tables
// it returns a list of column meta data
List<ColumnInformation> columnInformations = new List<ColumnInformation>();
// Avoid SQL conncatenation if at all possible. NEVER concatenate where parameters into SQL commands and NEVER EVER with single quotes.
// Here table name requires concatenation but the select parameter TableName does not.
string selectCmdString = "SELECT column_name,data_type,character_maximum_length FROM " + dbName + ".information_schema.columns WHERE table_name = @TableName";
// Use parameters. Get everything ready first, don't open connections prematurely and only wrap error prone code in try blocks.
SqlCommand cmd = new SqlCommand(selectCmdString, conn);
SqlParameter tableNameParameter = new SqlParameter("@TableName", tableName);
cmd.Parameters.Add(tableNameParameter);
// Use a DataReader since you cannot modify this data anyway.
// This also shows an appropriate use of a try block to ensure a connection gets closed,
// but better yet, open your reader with the CommandBehavior set to close
// and get rid of this try block altogether
try
{
//Reconsider use of a module or global level connection. May be better to create a new here.
conn.Open();
SqlDataReader reader = cmd.ExecuteReader();
//Favor OOP styles rather than indexes and arrays and repeated calls to determine things like Rows.Count in a loop
while(reader.Read())
{
// Favor explicit member access rather than index acess.
//YOUR HOMEWORK! Study DataReader access and rewrite the code below to handle possible nulls in length field. Use a method based on evaluating conditionals, DO NOT use a method based on a try block.
ColumnInformation columnInformation = new ColumnInformation(reader["column_name"].ToString(), reader["data_type"].ToString(), (int)reader["character_maximum_length"].ToString());
columnInformations.Add(columnInformation);
}
reader.Close();
}
finally
{
// The only reason to use the try is to make sure the connection gets closed here. A better approach
// is to use the CommandBehavior.CloseConnection option and get rid of the try finally block completely.
// But NEVER just wrap a bunch of code in try blocks arbitrarily, swallow any errors and return a null.
conn.Close();
}
return columnInformations;
}
}
public class ColumnInformation
{
private string _columnName;
private string _dataType;
private int _columnLength;
public string ColumnName
{
get { return _columnName; }
}
public string DataType
{
get { return _dataType; }
}
public int ColumnLength
{
get { return _columnLength; }
}
public ColumnInformation(string columnName, string dataType, int columnLength)
{
_columnName = columnName;
_dataType = dataType;
_columnLength = columnLength;
}
}
感谢很多...这真的很有帮助。帮助我重新思考我的编码方法和标准。现在必须重新排列我的代码。 ThnQ – NewBie 2011-03-13 08:22:23