如何启动数据库事务,在MySQL上运行多个查询然后使用c#提交或回滚?

时间:2015-01-12 00:43:19

标签: c# mysql winforms transactions

我有一个允许我在MySQL数据库上运行查询的泛型类。

我在这个类中看到的唯一问题是它打开连接运行查询并关闭连接。

现在,我需要能够

  1. START TRANSACTION;
  2. SELECT ...
  3. INSERT INTO table1...
  4. INSERT INTO table2...
  5. INSERT INTO table3...
  6. 如果以上所有查询均有效,则COMMIT;无法ROLLBACK;
  7. 是的,我需要一个事务,我需要确保所有查询都运行100%,或者我需要在重新开始之前回滚并更正错误。

    如何修改我的课程以允许我处理上述步骤?

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    using MySql.Data.MySqlClient;
    using System.Windows.Forms;
    
    
    namespace RM
    {
        public class dbConnetion
        {
            //private OdbcConnection conn; 
            private static readonly string mServer = "localhost";
            private static readonly string mDatabase = "my_db_name";
            private static readonly string mUid = "my_db_user";
            private static readonly string mPassword = "my_user_password";
            private static readonly string mPort = "3306";
            private string conn_string = String.Format("server={0};user={1};database={2};port={3};password={4};", mServer, mUid, mDatabase, mPort, mPassword);
    
    
            public string SYSTEM_NAME { get; set; }
    
            public dbConnetion()
            {
                Initilize_System_Settings();
            }
    
            // query the data base
            public IEnumerable<T> getData<T>(string query, List<MySqlParameter> pars, Func<IDataRecord, T> transform)
            {
                using (var conn = new MySqlConnection(conn_string))
                using (var cmd = new MySqlCommand(query, conn))
                {
                    if (pars != null)
                    {
                        foreach (MySqlParameter p in pars)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
    
                    conn.Open();
    
                    using (var rdr = cmd.ExecuteReader())
                    {
    
                        while (rdr.Read())
                        {
                            yield return transform(rdr);
                        }
                    }
    
                    conn.Close();
                }
            }
    
            // query the data base
            public T getValue<T>(string query, List<MySqlParameter> pars)
            {
                T value;
                using (var conn = new MySqlConnection(conn_string))
                using (var cmd = new MySqlCommand(query, conn))
                {
    
                    if (pars != null)
                    {
                        foreach (MySqlParameter p in pars)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
    
    
                    try
                    {
                        conn.Open();
                        object rawValue = cmd.ExecuteScalar();
    
                        if (rawValue != null)
                        {
                            value = (T)Convert.ChangeType(rawValue, typeof(T));
                        }
                        else
                        {
                            value = default(T);
                        }
    
                    }
                    catch (Exception ex)
                    {
    
                        Common.Alert(ex.ToString(), "SQL Error");
                        value = default(T);
    
                    }
                    finally
                    {
                        conn.Close();
                    }
    
                }
    
                return value;
            }
    
            public bool processQuery(string strSQL, List<MySqlParameter> pars)
            {
                bool toReturn = true;
                using (var conn = new MySqlConnection(this.conn_string))
                using (var cmd = new MySqlCommand(strSQL, conn))
                {
    
                    foreach (MySqlParameter param in pars)
                    {
                        cmd.Parameters.Add(param);
                    }
    
                    try
                    {
                        conn.Open();
                        cmd.ExecuteNonQuery();
                    }
                    catch (MySqlException ex)
                    {
                        Common.Alert(ex.ToString(), "SQL Error");
                        toReturn = false;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
    
                return toReturn;
            }
        }
    }
    

    我的第一个想法是在getData方法中添加一个新参数,以便在有开放式交易时允许我不打开/关闭连接,例如

    // query the data base
            public IEnumerable<T> getData<T>(string query, List<MySqlParameter> pars, Func<IDataRecord, T> transform, bool inTransaction = false)
            {
                using (var conn = new MySqlConnection(conn_string))
                using (var cmd = new MySqlCommand(query, conn))
                {
                    if (pars != null)
                    {
                        foreach (MySqlParameter p in pars)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
                    if(! inTransaction){
                        conn.Open();
                    }
                    using (var rdr = cmd.ExecuteReader())
                    {
    
                        while (rdr.Read())
                        {
                            yield return transform(rdr);
                        }
                    }
                    if(! inTransaction){
                        conn.Close();
                    }
                }
            }
    

    但我认为由于using声明

    ,这不会起作用

2 个答案:

答案 0 :(得分:0)

trans = Conn.BeginTransaction();
trans.Commit();
trans.Rollback();

Cannot access SqlTransaction object to rollback in catch block

答案 1 :(得分:0)

您必须确定从何处开始和结束交易,

using (var conn = new MySqlConnection(conn_string))
{
    var tx = conn.BeginTransaction();
    try
    {
        using (var cmd1 = new MySqlCommand(query1, conn))
        {
           cmd1.Transaction = tx;
           //do cmd 1 stuff here
        }

        using (var cmd2 = new MySqlCommand(query2, conn))
        {
           cmd2.Transaction = tx;
           //do cmd 1 stuff here
        }

       //do other commands....

       tx.Commit(); //or Rollback() based on results
    }
    catch (Exception ex)
    {
       tx.Rollback();
       throw ex;
    }
}