尝试Catch Finally - 处理读者

时间:2012-12-05 13:43:31

标签: c#

在C#中,我在代码中使用TRY..CATCH..FINALLY块来执行存储过程。

如果有异常,那么在我的FINALLY我想要关闭阅读器 - PolicyResult以及连接。

然而,我收到错误

  

当前上下文中不存在名称PolicyResult

PolicyResultTRY中定义的DataReader,但在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;
        }
    }

11 个答案:

答案 0 :(得分:5)

考虑使用using关键字

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

您还可以为usingSqlConnection对象定义SqlCommand范围。关闭范围后,将丢弃对象。

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
        }
    }
}

答案 1 :(得分:4)

因为您在try块中声明的所有内容在除嵌套和父级之外的其他块中不可见。在外面宣布它。

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

比检查它是否为空

 finally
 {
   if(PolicyResult!=null) PolicyResult.Close();
   objConn.Close();
 }

答案 2 :(得分:1)

PolicyResult在try块的范围内定义,因此在它之外不可用(例如,在finally块中。

答案 3 :(得分:1)

<{1}}中定义的只有<{> try {...}才可见。如果您想访问try { ... }区块中的PolicyResult,则需要在<{em>} 区块内声明

执行此操作的首选方法是使用finally块,但这会自动保证正确处理并基本上使try { ... }块过时:

using (....) { .... }

答案 4 :(得分:0)

错误是正确的,它确实不存在,因为当您使用try / catch创建范围时,在该范围外创建的任何变量都不会在范围之外被识别。

您可以通过在 try / catch块之前将变换移动到来轻松解决此问题:

SqlDataReader PolicyResult;
// Other variable declerations

try
{
}
finally
{
  // PolicyResult was decleared OUTSIDE the try block so it is known here.
}

答案 5 :(得分:0)

PolicyResult声明之前定义try

SqlDataReader PolicyResult = null;

答案 6 :(得分:0)

如果你想在catch和/或最后使用它,那么在try块之前声明SqlDataReader PolicyResult

答案 7 :(得分:0)

PolicyResult对象在 try 块的范围内声明,因此它不存在或无法从 finally 块中访问。将声明移到try连接对象声明旁边的try。

答案 8 :(得分:0)

try {}定义了与finally {}

分开的范围

您必须在try之外声明PolicyResult,最后将其初始化为null,并在关闭之前检查是否为null。

答案 9 :(得分:0)

那是因为他们处于不同的范围。

尝试在try catch之前声明变量:

SqlDataReader PolicyResult;

try
{
    // assign PolicyResult
}
catch
{
}
finally
{
    // use PolicyResult
}

答案 10 :(得分: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应用程序,最好通过会话管理系统初始化连接,该会话管理系统将在页面加载时或第一个查询执行后立即打开连接。这样,您的连接打开和关闭逻辑就在一个地方。然后可以安全地假设连接确实在任何后续代码中连接,并且您可以更轻松地处理任何特定于事务的错误。