Эта операция IfxTransaction завершена; он больше не пригоден для использования - PullRequest
1 голос
/ 26 июня 2011

Q:

Когда я использую транзакции, я получаю следующую ошибку примерно в 1 из каждых 100 записей.

Эта операция IfxTransaction завершена; Это больше не может использоваться

Я не могу ожидать, когда произойдет ошибка или в чем причина этой ошибки.

Я пытаюсь вставить около 607 записи в ту же транзакцию.

Мой код:

 public static int InsertGroups(List<Group> groups)
        {
            DBConnectionForInformix con = new DBConnectionForInformix("");
            con.Open_Connection();
            con.Begin_Transaction();

            int affectedRow = -1;
            Dictionary<string, string> groupsParameter = new Dictionary<string, string>();
            try
            {
                foreach (Group a in groups)
                {
                    groupsParameter.Add("id", a.GroupId.ToString());
                    groupsParameter.Add("name", a.Name);
                    groupsParameter.Add("studentcount", a.StudentCount.ToString());
                    groupsParameter.Add("divisiontag", a.DivisionTag.ToString());
                    groupsParameter.Add("entireclass", a.EntireClass.ToString());
                    groupsParameter.Add("classid", a.ClassId.ToString());
                    groupsParameter.Add("depcode", a.DepCode.ToString());
                    groupsParameter.Add("studycode", a.StudyCode.ToString());
                    groupsParameter.Add("batchnum", a.BatchNum.ToString());
                    affectedRow = DBUtilities.InsertEntityWithTrans("groups", groupsParameter, con);
                    groupsParameter.Clear();
                    if (affectedRow < 0)
                    {
                        break;
                    }
                }

                if (affectedRow > 0)
                {
                    con.current_trans.Commit();
                }
            }
            catch (Exception ee)
            {
                string message = ee.Message;
            }

            con.Close_Connection();
            return affectedRow;

        }

 public void Begin_Transaction()
        {
            if (this.connection.State == ConnectionState.Open)
            {
                this.current_trans = this.connection.BeginTransaction(IsolationLevel.Serializable);
            }
        }

public static int InsertEntityWithTrans(string tblName, Dictionary<string, string> dtParams, DBConnectionForInformix current_conn)
        {
            int Result = -1;
            string[] field_names = new string[dtParams.Count];
            dtParams.Keys.CopyTo(field_names, 0);
            string[] field_values = new string[dtParams.Count];
            string[] field_valuesParam = new string[dtParams.Count];
            dtParams.Values.CopyTo(field_values, 0);
            for (int i = 0; i < field_names.Length; i++)
            {
                field_valuesParam[i] = "?";
            }
            //----------------------------------------------------------------------------------------------------------------------------------------------
            string insertCmd = @"INSERT INTO " + tblName + " (" + string.Join(",", field_names) + ") values (" + string.Join(",", field_valuesParam) + ")";
            //----------------------------------------------------------------------------------------------------------------------------------------------

            IfxCommand com = new IfxCommand(insertCmd);
            for (int j = 0; j < field_names.Length; j++)
            {
                com.Parameters.Add("?", field_values[j]);
            }
            try
            {

                Result = current_conn.Execute_NonQueryWithTransaction(com);
                if (current_conn.connectionState == ConnectionState.Open && Result > 0)//OK: logging
                {
                    # region // Log Area

                    #endregion
                }
            }
            catch (Exception ex)
            {

                throw;
            }

            return Result;
        }

public int Execute_NonQueryWithTransaction(IfxCommand com)
        {
            string return_msg = "";
            int return_val = -1;
            Open_Connection();
            com.Connection = this.connection;
            com.Transaction = current_trans;
            try
            {
                return_val = com.ExecuteNonQuery();

            }
            catch (IfxException ifxEx)// Handle IBM.data.informix : mostly catched
            {
                return_val = ifxEx.Errors[0].NativeError;
                return_msg = return_val.ToString();
            }
            catch (Exception ex)// Handle all other exceptions.
            {
                return_msg = ex.Message;
            }
            finally
            {
                if (!string.IsNullOrEmpty(return_msg))//catch error
                {
                    //rollback
                    current_trans.Rollback();
                    Close_Connection();
                    connectionstate = ConnectionState.Closed;
                }

            }
            return return_val;
        }

1 Ответ

3 голосов
/ 26 июня 2011

Вы, похоже, обрабатываете ошибки и откатываете транзакцию в двух местах (в Execute_NonQueryWithTransaction и в InsertGroups.

И возврат из Execute_NonQueryWithTransaction используется как для возврата кодов ошибок, так и длявозвращаются затронутые строки. Но в InsertGroups он проверяется только как на затронутые строки.

Может быть, код ошибки из Execute_NonQueryWithTransaction (поэтому откат транзакции) рассматривается как успех (вставленные строки) в InsertGroups и фиксация завершается неудачей?

В целом, код нуждается в значительной очистке:

  1. Блок перехвата, который только выбрасывает, не имеет смысла и просто добавляет шум.
  2. Простоиспользуйте исключения для обработки ошибок, все нормальные возвраты должны указывать на успех.
...