0

データベースから約 20,000 レコードを選択して、1 つずつ更新しています。
このエラーを探したところ、CommandTimeout を設定すると役立つことがわかりましたが、私の場合はそうではありませんでした。

        public void Initialize()
    {
        MySqlConnectionStringBuilder SQLConnect = new MySqlConnectionStringBuilder();
        SQLConnect.Server = SQLServer;
        SQLConnect.UserID = SQLUser;
        SQLConnect.Password = SQLPassword;
        SQLConnect.Database = SQLDatabase;
        SQLConnect.Port = SQLPort;
        SQLConnection = new MySqlConnection(SQLConnect.ToString());
    }

        public MySqlDataReader SQL_Query(string query)
    {
        MySqlCommand sql_command;
        sql_command = SQLConnection.CreateCommand();
        sql_command.CommandTimeout = int.MaxValue;
        sql_command.CommandText = query;
        MySqlDataReader query_result = sql_command.ExecuteReader();
        return query_result;
    }

        public void SQL_NonQuery(string query)
    {
        MySqlCommand sql_command;
        sql_command = SQLConnection.CreateCommand();
        sql_command.CommandTimeout = int.MaxValue;
        sql_command.CommandText = query;
        sql_command.ExecuteNonQuery();
    }

そして、選択クエリを作成する私の方法は次のとおりです。

        public void CleanRecords()
    {
        SQLActions.Initialize();
        SQLActions.SQL_Open();
        MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
        while(cashData.Read()){
            if(cashData["income_money"].ToString() == cashData["total"].ToString()){
                UpdateRecords(cashData["id"].ToString());
            }
        }
        SQLActions.SQL_Close();
    }

そして、更新を行うメソッドは次のとおりです。

        public void UpdateRecords(string rowID)
    {
        SQLActions.Initialize();
        SQLActions.SQL_Open();
        SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id`='" + rowID + "'");
        SQLActions.SQL_Close();
    }

データベース構造を変更することは、私にとって選択肢ではありません。
タイムアウトをintの最大値に設定すると問題が解決すると思いましたが、私の場合はうまくいかないようです。何か案は?:)

EDIT:私が得るエラーは「データの読み取り中に致命的なエラーが発生しました」です。





アップデート:

        public void CleanRecords()
    {
        StringBuilder dataForUpdate = new StringBuilder();
        string delimiter = "";

        SQLActions.Initialize();
        SQLActions.SQL_Open();
        MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
        while (cashData.Read())
        {
            if (cashData["income_money"].ToString() == cashData["total"].ToString())
            {
                dataForUpdate.Append(delimiter);
                dataForUpdate.Append("'" + cashData["id"].ToString() + "'");
                delimiter = ",";
            }
        }
        SQLActions.SQL_Close();
        UpdateRecords(dataForUpdate.ToString());
    }

    public void UpdateRecords(string rowID)
    {
        SQLActions.Initialize();
        SQLActions.SQL_Open();
        SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id` IN (" + rowID + ")");
        SQLActions.SQL_Close();
    }
4

2 に答える 2

1

使用できる場合があります

UPDATE cash_data .... WHERE id IN (SELECT ....)

すべてを一度に行います。それ以外の場合は、2 つの手順でそれを行うことができます。最初に select ですべての ID を収集し、接続を閉じてから、obne go ですべての ID を使用して更新を行います。2 番目のオプションのコードは次のようになります。

    public void CleanRecords()
    {
        StringBuilder builder = new StringBuilder();
        string delimiter = "";

        SQLActions.Initialize();
        SQLActions.SQL_Open();
        MySqlDataReader cashData = SQLActions.SQL_Query("SELECT `cash`.`id`, SUM(`cash`.`income_money`) AS `income_money`, `cash_data`.`total` FROM `cash_data` JOIN `cash` ON `cash`.`cash_data_id` = `cash_data`.`id` WHERE `user`='0' AND `cash_data`.`paymentterm_id`='0' OR `cash_data`.`paymentterm_id`='1' GROUP BY `cash_data_id`");
        while(cashData.Read()){
            if(cashData["income_money"].ToString() == cashData["total"].ToString()){
                builder.Append(delimiter);
                builder.Append("'" + cashData["id"].ToString() + "'");
                delimiter = ",";       
            }
        }
        SQLActions.SQL_Close();

        UpdateRecords(builder.ToString());  


    }

public void UpdateRecords(string rowIDs)
{
    SQLActions.Initialize();
    SQLActions.SQL_Open();
    SQLActions.SQL_NonQuery("UPDATE `cash_data` SET `end_date`='" + GetMeDate() + "', `user`='1' WHERE `id` IN (" + rowIDs + ")";
    SQLActions.SQL_Close();
}
于 2013-06-17T08:49:57.283 に答える
0

複数の問題があります:

最初: データ リーダーを使用して約 20K の情報を読み取り、リーダー自体で 1 つずつ更新を行います。Reader は、終了するまで接続を開いたままにします。したがって、これは良い方法ではありません。解決策: Data Adapter を使用して情報を読み取ることができます。

2 つ目: 1 つずつ更新するのではなく、一度にまとめて更新できます。一括操作には複数のオプションがあります。SQL では、XML 形式で情報を送信するか、Table Valued Parameter (TVP) を使用できます ( http://www.codeproject.com/Articles/22205/ADO-NET-and-OPENXML-to-Perform-Bulk -Database-Opera ) または ( http://dev.mysql.com/doc/refman/5.5/en/load-xml.html )

于 2013-06-17T08:30:25.037 に答える