0

C# ではTRY..CATCH..FINALLY、コード内でストアド プロシージャの実行を囲むブロックを使用しています。

例外がある場合はFINALLY、リーダーと接続を閉じたいと思いPolicyResultます。

ただし、エラーが発生します

名前 PolicyResult は現在のコンテキストに存在しません

PolicyResultで定義されている DataReader ですが、セクションTRYで認識されていないようです。FINALLY

なんで?

        public static IEnumerable GetPolicies(int? MasterPkgID)
        {
            // Create a list of policies belonging to the master package.
            List<AdditionalInterestPolicyData> additionalInterestPolicyData = new List<AdditionalInterestPolicyData>();

            // Set the SQL connection to the database.
            SqlConnection objConn = new SqlConnection(ConfigurationManager.ConnectionStrings["QUESTIONNAIRE2"].ConnectionString);

            try
            {
               // Open the connection.
               objConn.Open();

               // Get the list of policies by executing a stored procedure.
               SqlCommand PolicyCmd = new SqlCommand("p_expapp_get_policy_detail_by_master_pkg", objConn);
               PolicyCmd.Parameters.Clear();
               PolicyCmd.CommandType = CommandType.StoredProcedure;
               PolicyCmd.Parameters.Add("@a_master_package_iden_key", SqlDbType.Int).Value = MasterPkgID;

               SqlDataReader PolicyResult = PolicyCmd.ExecuteReader();

               // Loop thru the results returned.
               while (PolicyResult.Read())
               {
                  // Add to the list of policies - creates a new row for the collection.
                  additionalInterestPolicyData.Add(new AdditionalInterestPolicyData(
                                                         Int32.Parse(PolicyResult["affiliate_id"].ToString()),
                                                         Int32.Parse(PolicyResult["master_package_iden_key"].ToString())
                                                                                   )
                                                  );
               }
            }
            catch (Exception ex)
            {
                bError = true;
            }
            finally
            {
                PolicyResult.Close();
                objConn.Close();
            }

            return additionalInterestPolicyData;
        }
    }
4

11 に答える 11

5

usingキーワードの使用を検討してください

using (System.Data.SqlClient.SqlDataReader r = PolicyCmd.ExecuteReader())
{
    //DO STUFF
}

およびオブジェクトusingのスコープを定義することもできます。スコープが閉じられると、オブジェクトは破棄されます。SqlConnectionSqlCommand

using (System.Data.SqlClient.SqlConnection connection = new System.Data.SqlClient.SqlConnection())
{
    ...
    using (System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand())
    {
        ...
        using (System.Data.SqlClient.SqlDataReader reader = new System.Data.SqlClient.SqlDataReader())
        {
            //DO STUFF
        }
    }
}
于 2012-12-05T13:46:38.497 に答える
4

try ブロックで宣言するものはすべて、ネストされたブロックと親を除く他のブロックでは表示されないためです。外に宣言します。

 SqlDataReader PolicyResult=null;
 try
 {
   ...
   PolicyResult = PolicyCmd.ExecuteReader();
 }

それがnullでないかどうかを確認するよりも

 finally
 {
   if(PolicyResult!=null) PolicyResult.Close();
   objConn.Close();
 }
于 2012-12-05T13:45:54.073 に答える
1

の内部で定義されたものは、内部でのみ表示try {...}されます。ブロック内の にアクセスする場合は、ブロックので宣言する必要があります。try { ... }PolicyResultfinallytry { ... }

ただし、これを行うための推奨される方法は、using (....) { .... }ブロックを使用することです。これにより、適切な破棄が自動的に保証され、基本的にfinallyブロックが廃止されます。

try
{
    // Open the connection.
    objConn.Open();

    // Get the list of policies by executing a stored procedure.
    using (SqlCommand PolicyCmd = new SqlCommand("p_expapp_get_policy_detail_by_master_pkg", objConn))
    {
           PolicyCmd.Parameters.Clear();
           PolicyCmd.CommandType = CommandType.StoredProcedure;
           PolicyCmd.Parameters.Add("@a_master_package_iden_key", SqlDbType.Int).Value = MasterPkgID;

           using (SqlDataReader PolicyResult = PolicyCmd.ExecuteReader())
           {
               // Loop thru the results returned.
               while (PolicyResult.Read())
               {
                  // do your stuff here....
               }
           }
    }
}
于 2012-12-05T13:49:09.273 に答える
1

PolicyResult は try ブロックのスコープ内で定義されているため、その外側 (たとえば、finally ブロック内) では使用できません。

于 2012-12-05T13:46:06.540 に答える
0

少なくともtryブロックの外でPolicyResultを宣言する必要があり、外部でもインスタンス化することをお勧めします。このようなものが機能するはずです:

public static IEnumerable GetPolicies(int? MasterPkgID)
{
    // Create a list of policies belonging to the master package.
    List<AdditionalInterestPolicyData> additionalInterestPolicyData = new List<AdditionalInterestPolicyData>();

    // Set the SQL connection to the database.
    SqlConnection objConn = new SqlConnection(ConfigurationManager.ConnectionStrings["QUESTIONNAIRE2"].ConnectionString);

    SqlDataReader PolicyResult = null;

    try
    {
        // Open the connection.
        objConn.Open();

        // Get the list of policies by executing a stored procedure.
        SqlCommand PolicyCmd = new SqlCommand("p_expapp_get_policy_detail_by_master_pkg", objConn);
        PolicyCmd.Parameters.Clear();
        PolicyCmd.CommandType = CommandType.StoredProcedure;
        PolicyCmd.Parameters.Add("@a_master_package_iden_key", SqlDbType.Int).Value = MasterPkgID;

        PolicyResult = PolicyCmd.ExecuteReader();
        // Loop thru the results returned.
        while (PolicyResult.Read())
        {
            // Add to the list of policies - creates a new row for the collection.
            additionalInterestPolicyData.Add(new AdditionalInterestPolicyData(
                                                    Int32.Parse(PolicyResult["affiliate_id"].ToString()),
                                                    Int32.Parse(PolicyResult["master_package_iden_key"].ToString())
                                                                            )
                                            );
        }
    }
    catch (Exception ex)
    {
        bError = true;
    }
    finally
    {
        if(PolicyResult != null) PolicyResult.Close();
        objConn.Close();
    }

    return additionalInterestPolicyData;
}

ただし、これが最善のアプローチではない可能性があることに注意してください。まず第一に、おそらくすでにデータベース接続を開いているはずです。トランザクションごとにデータベース接続を開いたり閉じたりすると、非常に手間がかかります。接続を閉じるのを簡単に忘れることができます。エラーが発生した場合は、コンテキストによってはログがだまされる可能性があります。これがWebアプリの場合は、ページが読み込まれるとすぐに、または最初のクエリが実行されるとすぐに接続を開くセッション管理システムを介して接続を初期化するのが最善です。このようにして、接続の開閉ロジックがすべて1か所にまとめられます。そうすれば、接続が実際に後続のコードで接続されたと想定するのが安全になり、トランザクション固有のエラーをもう少し簡単に処理できます。

于 2012-12-05T13:53:04.107 に答える
0

エラーは正しいです。実際には存在しません。なぜなら、try/catch を使用してscopeを作成すると、そのスコープで作成された変数はスコープ外では認識されないからです。

これは、宣言をtry/catch ブロックの前に移動することで簡単に修正できます。

SqlDataReader PolicyResult;
// Other variable declerations

try
{
}
finally
{
  // PolicyResult was decleared OUTSIDE the try block so it is known here.
}
于 2012-12-05T13:46:21.157 に答える
0

ステートメントPolicyResultの前に定義します。try

SqlDataReader PolicyResult = null;
于 2012-12-05T13:46:37.037 に答える
0

catch および/または finally で使用する場合は、try ブロックの前に SqlDataReader PolicyResult を宣言します。

于 2012-12-05T13:46:44.737 に答える
0

PolicyResult オブジェクトはtryブロックのスコープ内で宣言されているため、存在しないか、finallyブロック内からアクセスできません。接続オブジェクトの宣言の隣の try の外に宣言を移動します。

于 2012-12-05T13:47:02.813 に答える
0

try {} は、finally {} とは別のスコープを定義します

try の外で PolicyResult を宣言し、finally を null に初期化し、finally を閉じる前に null かどうかを確認する必要があります。

于 2012-12-05T13:47:22.227 に答える
0

それは、それらが異なるスコープにあるためです。

try キャッチの前に変数を宣言してみてください。

SqlDataReader PolicyResult;

try
{
    // assign PolicyResult
}
catch
{
}
finally
{
    // use PolicyResult
}
于 2012-12-05T13:48:29.687 に答える