이 코드는 계속 진행되고 있습니다. 필자는이 코드를 완벽하게 다시 작성했으며, 가장 짧은 코드 또는 최선의 방법은 아니지만 더 많은 것을 배우거나 작업 할 수있는 영역을 설명하기 위해 작성되었습니다.
예외 처리, 특히 사용시기와 용도에 대해 연구하십시오. 오류를 삼키는 try 블록을 작성하지 마십시오. 이 메쏘드가 null을 리턴한다면 당신은 무엇을 할 계획입니까? 테이블 이름이 나빴나요? 연결이 실패 했습니까? 사용자가 오류를 수정할 수도 있지만 그렇지 않을 수도 있습니다. 이제 아무도 그것이 무엇인지 알 수 없습니다.
null을 사용하여 수행 한 작업에 따라 여기에서도 오류가 발생한다는 것을 아무도 알지 못할 수도 있습니다. 이런 오류는 절대로 삼가하십시오. 오류가 발생한 지점에서 응용 프로그램이 실패해야합니다. 이것도 null을 돌려주는 것에주의 해주세요. 널 (null)을 리턴하고 나서 다른 작업을하면 나중에 어딘가에서 응용 프로그램이 실패 할 수 있으며 원래의 오류는 찾아서 수정하기가 훨씬 더 어려워집니다. 프레임 워크를 작성할 때 때때로이 스타일에서 null을 반환 할 수 있습니다. 일반 응용 프로그램의 경우 일반적으로 필요하지 않으며 거의 좋은 아이디어가 아닙니다.
일반적으로 양질의 프로덕션 코드에는 예상 할 수있는 모든 것을 처리하기 위해 조건을 사용해야하므로 예외 처리가 거의 포함되지 않습니다. 당신이 예상 할 수없는 것은 대개 또한 처리 할 수 없습니다. 리소스를 정리하기 위해 존재하는 많은 try ... finally 블록이있을 수 있지만 응용 프로그램에는 실제 시도 및 검색 검정이 거의 포함되어 있지 않아야합니다. 일반적으로 오류가 응용 프로그램이 종료되기 전에 사용자에게 알리는 최종 핸들러로 호출 스택을 전파하도록합니다.
다음은 여전히 작성할 수있는 최상의 코드는 아닙니다. 나는 당신의 원본에 가깝게 유지하고 합리적이었고 명확하게하기 위해 몇 가지 단축키를 제거했습니다. 차이점을 연구하고 거기서 가십시오.
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