当分配给命令的连接处于挂起的本地trans时,ExecuteReader需要命令才能具有事务

时间:2014-01-10 07:22:52

标签: c# ado.net

我必须在单个事务中插入两个表,必须实现的查询在下面。其次在 SqlDataReader read = comm.ExecuteReader();

获取异常
public void SqlExecuteNonQuery(Customer obj)
{
  //string query = "DECLARE @_customerID int ";
  string query1 = "INSERT INTO customer (customerName,customerSex,Email) VALUES ('" + obj.name + "','" + obj.sex + "','" + obj.Email + "') ";
  //string query2 = "SET @_customerID =@@identity ";
  string query3 = "INSERT INTO customerDetails(customerID,customerAddress,customerPhone) VALUES (" + obj.id + ",'" + obj.address + "','" + obj.phone + "') ";

  string CS = ConnectionName;

  using (SqlConnection conn = new SqlConnection(CS))
  {
     conn.Open();
     using (SqlCommand command = new SqlCommand("SELECT Email FROM Customer where Email ='" + obj.Email + "'", conn))
     {
         SqlDataReader reader = command.ExecuteReader();

         try
         {
            if (reader.Read())
            {
                throw new Exception("User already exist for the email");
            }

            else
            {
                reader.Close();
                using (SqlCommand cmd = GetCommand(query1, conn))
                {
                    SqlTransaction transaction;
                    transaction = conn.BeginTransaction();

                    try
                    {
                       cmd.Transaction = transaction;
                       cmd.ExecuteNonQuery();
                       using (SqlCommand comm = new SqlCommand("Select customerID from Customer where email = '" + obj.Email + "'", conn))
                       {
                          SqlDataReader read = comm.ExecuteReader();

                          try
                          {
                             while (read.Read())
                             {
                                obj.id = (int)read[0];
                             }
                             using (SqlCommand cmd1 = GetCommand(query3, conn))
                             {
                                try
                                {
                                   cmd1.ExecuteNonQuery();
                                }
                                catch (Exception ex1)
                                {
                                   Console.WriteLine("Comit Exception Type: {0}", ex1.GetType());
                                   Console.WriteLine("error in inserting - {0}", ex1.Message);
                                   try
                                   {
                                      transaction.Rollback();
                                   }
                                   catch (Exception ex2)
                                   {
                                      Console.WriteLine("RollBack Exception Type: {0}", ex2.GetType());
                                      Console.WriteLine("Message: {0}", ex2.Message);
                                   }
                                }
                             }
                             transaction.Commit();
                             Console.WriteLine("Successfull transaction");

                          }
                          catch (Exception ex)
                          {
                             Console.WriteLine("Error type:", ex.GetType());
                             Console.WriteLine("Message:", ex.Message);

                          }
                          finally {
                            read.Close();
                          }

                       }
                    }

                    catch (Exception ex)
                    {
                       Console.WriteLine("Comit Exception Type: {0}", ex.GetType());
                       Console.WriteLine("error in inserting - {0}", ex.Message);
                       try
                       {
                          transaction.Rollback();
                       }
                       catch (Exception ex2)
                       {
                         Console.WriteLine("RollBack Exception Type: {0}", ex2.GetType());
                         Console.WriteLine("Message: {0}", ex2.Message);
                       }
                    }
                    finally
                    {
                       transaction.Dispose();
                    }
                 }
              }
           }
           catch (Exception ex)
           {
              Console.WriteLine(ex.Message);
           }

       }
    }
}

2 个答案:

答案 0 :(得分:12)

问题是你在与cmd相同的连接上执行cmd1,所以在该连接上有一个打开的事务,但是你没有设置cmd1.Transaction ......所以解决方案就是

cmd1.Transaction = transaction;

之前

cmd1.ExecuteNonQuery();

答案 1 :(得分:6)

您可能需要考虑切换到使用TransactionScope,然后将其隐式用于其中的所有命令。你会用它来像:

using(var scope = new TransactionScope())
{
   using(var conn = new SqlConnection(/*...*/))
   {
      //As many nested commands, etc, using the above connection.
      //but don't need to create a SqlTransaction object nor
      //in any way reference the scope variable
   }
   scope.Complete();
}