Reputation: 59
In C#, I am using a TRY..CATCH..FINALLY
block in my code surrounding the executing of a stored procedure.
If there is an exception, then in my FINALLY
I want to close the reader - PolicyResult
as well as the connections.
However, I get an error
The name PolicyResult does not exist in the current context
PolicyResult
is the DataReader defined in the TRY
but it seems to not be recognized in the FINALLY
section.
Why?
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;
}
}
Upvotes: 1
Views: 9010
Reputation: 32571
Consider using the using
keyword
using (System.Data.SqlClient.SqlDataReader r = PolicyCmd.ExecuteReader())
{
//DO STUFF
}
You can also define using
scopes for the SqlConnection
and the SqlCommand
objects. After the scopes are closed, the objects will be disposed.
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
}
}
}
Upvotes: 5
Reputation: 6265
Because everything you declare in try block is not visible in other blocks excluding nested and parent. Declare it outside.
SqlDataReader PolicyResult=null;
try
{
...
PolicyResult = PolicyCmd.ExecuteReader();
}
Than check if it's not null
finally
{
if(PolicyResult!=null) PolicyResult.Close();
objConn.Close();
}
Upvotes: 5
Reputation: 35117
You need to at least declare PolicyResult outside of the try block and I'd recommend instantiating it outside as well. Something like this should work:
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;
}
It's worth noting however that this may not be the best approach. First of all you should probably already have your database connection open. Opening and closing your database connection for each transaction gets really messy really quick. You can easily forget to close the connection and if there's an error logging can be tricking depending on the context. If this is a web app it's best to initialize the connection through a session management system that will either open the connection as soon as the page loads or as soon as the first query is executed. This way your connection opening and closing logic is all in one place. Then it becomes safe to assume that the connection did actually connect in any subsequent code and you can handle any transaction specific errors with a bit more ease.
Upvotes: 0
Reputation: 755083
Any defined inside the try {...}
is visible only there - inside the try { ... }
. If you want to access the PolicyResult
in your finally
block - you need to declare it outside the try { ... }
block.
The preferred way of doing this would be to use a using (....) { .... }
block, however, which automatically guarantees proper disposal and basically makes the finally
block obsolete:
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....
}
}
}
}
Upvotes: 1
Reputation: 7336
Thats becouse they are in different scopes.
Try to declare the variable before the try catch:
SqlDataReader PolicyResult;
try
{
// assign PolicyResult
}
catch
{
}
finally
{
// use PolicyResult
}
Upvotes: 0
Reputation: 109762
The try {} defines a scope separate to the finally {}
You must declare PolicyResult outside the try and finally, initialise it to null, and check if for nullness in finally before you close it.
Upvotes: 0
Reputation: 4379
The PolicyResult object is declared within the scope of the try block therefore it does not exist or is not accessible from within the finally block. Move the declaration outside of the try next to your declaration of the connection object.
Upvotes: 0
Reputation: 2481
Declare SqlDataReader PolicyResult before the try block if you wish to use it in catch and/or finally
Upvotes: 0
Reputation: 7759
Define PolicyResult
before the try
statement:
SqlDataReader PolicyResult = null;
Upvotes: 0
Reputation: 17395
The error is correct, it really dosn't exist, since when you use try/catch you create a scope, any variables created in that scope will not be known outside the scope.
You can easily fix this by moving the decleration to before the try/catch block:
SqlDataReader PolicyResult;
// Other variable declerations
try
{
}
finally
{
// PolicyResult was decleared OUTSIDE the try block so it is known here.
}
Upvotes: 0
Reputation: 29963
PolicyResult is defined within the scope of the try block, and is therefore not available outside it (in the finally block, for example.
Upvotes: 1