tags:

views:

125

answers:

6

What is wrong with the scope in the following code?

namespace t2
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ////// string connectionString = "Data Source=A-63A9D4D7E7834\\SQLEXPRESS;Initial Catalog=Test1;Integrated Security=True";
            //connection string i taken from the file class1.cs static class.

            try
            {
                string commandString = "Select * from Table_1";

                SqlConnection conn = new SqlConnection(Class1.connection);
                SqlCommand command = new SqlCommand(commandString, conn);
                conn.Open();

                // Start a local transaction.
                SqlTransaction sqlTran = conn.BeginTransaction();
                command.Transaction = sqlTran;

                try
                {
                    SqlDataReader reader = command.ExecuteReader();
                    GridView1.DataSource = reader;
                    GridView1.DataBind();
                }//try ends here.
                catch (SqlException ex)
                {
                    //Console.WriteLine(ex.Message);
                    try
                    {
                        // Attempt to roll back the transaction.
                        sqlTran.Rollback();
                    }
                    catch (Exception exRollback)
                    {
                        // Throws an InvalidOperationException if the connection
                        // is closed or the transaction has already been rolled
                        // back on the server.
                        Response.Write(exRollback.Message.ToString());
                    }
                    //    <snipped> build error message
                }//sql catch ends here
                catch (Exception all)
                {
                    try
                    {
                        // Attempt to roll back the transaction.
                        sqlTran.Rollback();
                    }
                    catch (Exception exRollback)
                    {
                        // Throws an InvalidOperationException if the connection
                        // is closed or the transaction has already been rolled
                        // back on the server.
                        Response.Write(exRollback.Message.ToString());
                    }

                    Response.Write(all.Message.ToString());
                }//catch all ends
            }//main try
            finally
            {
                // Commit the transaction.
                sqlTran.Commit();
                reader.Close();
                reader.Dispose();
                conn.Close();
                conn.Dispose();
             }//finally ends
        }//page load method ends

Errors displayed are:

Error   1   The name 'sqlTran' does not exist in the current context    D:\DOCUMENTSS\Visual Studio 2008\Projects\t2\t2\Default.aspx.cs 162 17  t2
Error   2   The name 'reader' does not exist in the current context D:\DOCUMENTSS\Visual Studio 2008\Projects\t2\t2\Default.aspx.cs 166 17  t2
Error   3   The name 'reader' does not exist in the current context D:\DOCUMENTSS\Visual Studio 2008\Projects\t2\t2\Default.aspx.cs 167 17  t2
Error   4   The name 'conn' does not exist in the current context   D:\DOCUMENTSS\Visual Studio 2008\Projects\t2\t2\Default.aspx.cs 169 17  t2

Error   5   The name 'conn' does not exist in the current context   D:\DOCUMENTSS\Visual Studio 2008\Projects\t2\t2\Default.aspx.cs 170 17  t2
+4  A: 

sqlTran is declared and initialized in the try block, but you're trying to access it in the catch and finally blocks, where it no longer exists in the scope. The same goes for reader and conn. You would need to declare the variables before the whole try-catch-finally block in order to access it in both.

ccomet
+4  A: 

Those variables are declared inside the try portions of your code. Inside the catch {} portions, those variables do not exist. To fix the problem, you need to declare the variables outside the try block (setting them to null), and then you can instantiate them in try block. Be sure to check for null values in the catch blocks.

expedient
okay but what do you mean by "Be sure to check for null values in the catch blocks." how and why??
in a catch block where you're trying to roll back sqlTran, for instance, it may be that the exception occurred before sqlTran was instantiated. This means the variable is null, and if you try to call its Rollback function, you'll get a null reference exception. Instead, if you say if (sqlTran != null) sqlTran.Rollback() you can avoid that problem.
expedient
A: 

Your SQL Transaction is inside your "main try" yet you try to use it in your "main finally", it needs to be outside main try to be used in the catch/finally blocks. Also, never .Commit inside a finally block - put it at the end of the main try just before the try finishes.

Adam
A: 

Your sqlTran is declared inside first try block, so it can not be accessed in the finally block,

try{
  define A
}
finally{
  cant access A here..
}

Your variable should be declared outside try block.

define A
try{
   do something with A
}
finally{
   can access A here...
}
Akash Kava
A: 

Declare your connection, command, and transaction outside of the first try. You can instantiate them inside the try, but make sure they're declared before you do something that can throw an error. If conn.Open() threw an error, your transaction would never have been declared. That's why the language doesn't let you use those variables in the catch/finally.

Kendrick
"That's why the language doesn't let you use those variables in the catch/finally." what do you mean, i am just interested.... scope is a problem for me not a benefit..
Scope has a purpose. Here, it's saving you from making a major programming mistake and possibly attempting to close an object that doesn't exist. The reason you're using try/catch is to keep your code from crashing to the end user, and the compiler is helping you to achive this goal.
Kendrick
+1  A: 

Here is an example from MSDN that explains how to typically use a SqlTransaction with in a method. Just like others have said, your BeginTransaction call should be outside of your try catch so that you will have access to it through all levels of the method's scope.

Hope this helps some.

Chris