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();
 }

比检查它是否不为空

 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 catch 之前声明变量:

SqlDataReader PolicyResult;

try
{
    // assign PolicyResult
}
catch
{
}
finally
{
    // use PolicyResult
}
于 2012-12-05T13:48:29.687 回答
0

错误是正确的,它确实不存在,因为当您使用 try/catch 创建一个范围时,在该范围内创建的任何变量都不会在范围外知道。

您可以通过将 decleration 移至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

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

于 2012-12-05T13:53:04.107 回答
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 和 finally 之外声明 PolicyResult,将其初始化为 null,并在关闭之前检查 finally 中是否为 null。

于 2012-12-05T13:47:22.227 回答