最初の質問:
と言う
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
接続は閉じられますか?技術的には、前のreturn
のように、最後の}
に到達することはありません。
2番目の質問:
今回は:
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
}
catch (Exception) { /*Handle error*/ }
ここで、try
のどこかでエラーが発生し、キャッチされると言います。接続はまだ閉じられますか?繰り返しになりますが、try
の残りのコードをスキップして、catch
ステートメントに直接移動します。
using
がどのように機能するかについて、あまりにも直線的に考えていますか?すなわち、using
スコープを出るときにDispose()
が単に呼び出されますか?
いずれにせよ、usingブロックが(正常終了またはエラーにより)終了すると、閉じられます。
私はそれがbetterになると思いますが、何が起こるかを見るのがずっと簡単だから後でサポートする新しいメンテナンスプログラマ向け:
using (SqlConnection connection = new SqlConnection(connectionString))
{
int employeeID = findEmployeeID();
try
{
connection.Open();
SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
command.CommandTimeout = 5;
command.ExecuteNonQuery();
}
catch (Exception)
{
/*Handle error*/
}
}
両方の質問に答えます。 usingステートメントはtry/finallyブロックにコンパイルされます
using (SqlConnection connection = new SqlConnection(connectionString))
{
}
と同じです
SqlConnection connection = null;
try
{
connection = new SqlConnection(connectionString);
}
finally
{
if(connection != null)
((IDisposable)connection).Dispose();
}
編集:使い捨てへのキャストの修正 http://msdn.Microsoft.com/en-us/library/yh598w02.aspx
これが私のテンプレートです。 SQLサーバーからデータを選択するために必要なものすべて。接続が閉じられて破棄され、接続と実行のエラーがキャッチされます。
string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString;
string selectStatement = @"
SELECT TOP 1 Person
FROM CorporateOffice
WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%'
ORDER BY IntelligenceQuotient DESC
";
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
{
if (dr.HasRows)
{
while (dr.Read())
{
Console.WriteLine(dr["Person"].ToString());
}
}
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
}
*改訂:2015-11-09 *
NickGの提案どおり。あまりにも多くの中括弧がある場合は、次のようにフォーマットしてください...
using (SqlConnection conn = new SqlConnection(connString))
using (SqlCommand comm = new SqlCommand(selectStatement, conn))
{
try
{
conn.Open();
using (SqlDataReader dr = comm.ExecuteReader())
if (dr.HasRows)
while (dr.Read()) Console.WriteLine(dr["Person"].ToString());
else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
}
catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
if (conn.State == System.Data.ConnectionState.Open) conn.Close();
}
繰り返しになりますが、EAやDayBreakのゲームで働いている場合、改行を忘れてもかまいません。なぜなら、それらは後で戻ってコードを見て、本当に気にする人のためだけのものだからです。私は正しいですか? 23行ではなく1行ということは、私がより良いプログラマーであることを意味しますよね?
using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); }
うん... OK私はそれを自分のシステムから取り出し、しばらく自分自身を面白くしました。続ける。
Disposeは、使用範囲を離れると呼び出されます。 「使用する」ことの意図は、開発者にリソースが確実に破棄されることを保証する方法を提供することです。
MSDN から:
Usingステートメントは、usingステートメントの終わりに到達したとき、または例外がスローされ、ステートメントの終わりの前に制御がステートメントブロックから離れたときに終了できます。
Using
は、割り当てられているオブジェクトの周辺でtry/finallyを生成し、Dispose()
を呼び出します。
Try/finallyブロックを手動で作成してDispose()
を呼び出す手間が省けます
最初の例では、C#コンパイラは実際にusingステートメントを次のように変換します。
SqlConnection connection = new SqlConnection(connectionString));
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
最後に、関数が戻る前にステートメントが常に呼び出されるため、接続は常に閉じられます。
したがって、2番目の例では、コードは次のようにコンパイルされます。
try
{
try
{
connection.Open();
string storedProc = "GetData";
SqlCommand command = new SqlCommand(storedProc, connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
return (byte[])command.ExecuteScalar();
}
finally
{
connection.Dispose();
}
}
catch (Exception)
{
}
例外はfinallyステートメントでキャッチされ、接続が閉じられます。例外は、外側のcatch節には表示されません。
try/catchブロック内に2つのusingステートメントを書いたところ、例外が発生していることがわかりました。 ShaneLS example と同じように、内部usingステートメント内に配置されている場合、同じ方法でキャッチされます。
try
{
using (var con = new SqlConnection(@"Data Source=..."))
{
var cad = "INSERT INTO table VALUES (@r1,@r2,@r3)";
using (var insertCommand = new SqlCommand(cad, con))
{
insertCommand.Parameters.AddWithValue("@r1", atxt);
insertCommand.Parameters.AddWithValue("@r2", btxt);
insertCommand.Parameters.AddWithValue("@r3", ctxt);
con.Open();
insertCommand.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
try/catchがどこに配置されていても、例外は問題なくキャッチされます。