0

ファイルを読み取り、Windows 8 64 ビット環境で MySQL ODBC 5.1 ドライバーを使用して MySQL データベースを更新する C# でループを実行しています。

操作は簡単

  1. カウント+1
  2. ファイルが存在するかどうかを確認する
  3. XMLファイル(XDocument)の読み込み
  4. XDocument からデータを取得する
  5. ODBC接続を開く
  6. MySQL データベースに対していくつかのストアド プロシージャを実行して、データを保存します。
  7. ODBC接続を閉じる

問題は、しばらくすると OdbcCommand.ExecuteNonQuery などでハングアップすることです。しがみつくのは常に同じ SP であるとは限りませんか?

これは本当の問題です。60,000 個のファイルをループする必要がありますが、一度に約 1000 個しか持続しません。

編集1:問題はここで何度も発生しているようです:

public bool addPublisherToGame(int inPublisherId, int inGameId)
        {
            string sqlStr;
            OdbcCommand commandObj;
            try
            {
                sqlStr = "INSERT INTO games_publisher_binder (gameId, publisherId) VALUE(?,?)";

                commandObj = new OdbcCommand(sqlStr, mainConnection);
                commandObj.Parameters.Add("@gameId", OdbcType.Int).Value = inGameId;
                commandObj.Parameters.Add("@publisherId", OdbcType.Int).Value = inPublisherId;

                if (Convert.ToInt32(executeNonQuery(commandObj)) > 0)
                    return true;
                else
                    return false;

            }
            catch (Exception ex)
            {
                throw (loggErrorMessage(this.ToString(), "addPublisherToGame", ex, -1, "", ""));
            }
            finally
            {

            }
        }


protected object executeNonQuery(OdbcCommand inCommandObj)
        {
            try
            {
                //FileStream file = new FileStream("d:\\test.txt", FileMode.Append, FileAccess.Write);

                //System.IO.StreamWriter stream = new System.IO.StreamWriter(file);
                //stream.WriteLine(DateTime.Now.ToString() + " - " + inCommandObj.CommandText);
                //stream.Close();
                //file.Close();

                //mainConnection.Open();
                return inCommandObj.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

in パラメータが正しいことがわかります

接続の開閉は、トップ メソッド for ever ループで行われます (finally を使用)。

編集2:

これは、情報を抽出してデータベースに保存するメソッドです。

public Boolean addBoardgameToDatabase(XElement boardgame, GameFactory gameFactory)
        {
            int incomingGameId = -1;
            XElement tmpElement;
            string primaryName = string.Empty;
            List<string> names = new List<string>();
            GameStorage externalGameStorage;

            int retry = 3;
            try
            {
                if (boardgame.FirstAttribute != null &&
                    boardgame.FirstAttribute.Value != null)
                {
                    while (retry > -1)
                    {
                        try
                        {
                            incomingGameId = int.Parse(boardgame.FirstAttribute.Value);

                            #region Find primary name
                            tmpElement = boardgame.Elements("name").Where(c => c.Attribute("primary") != null).FirstOrDefault(a => a.Attribute("primary").Value.Equals("true"));

                            if (tmpElement != null)
                                primaryName = tmpElement.Value;
                            else
                                return false;
                            #endregion

                            externalGameStorage = new GameStorage(incomingGameId,
                                                                primaryName,
                                                                string.Empty,
                                                                getDateTime("1/1/" + boardgame.Element("yearpublished").Value),
                                                                getInteger(boardgame.Element("minplayers").Value),
                                                                getInteger(boardgame.Element("maxplayers").Value),
                                                                boardgame.Element("playingtime").Value,
                                                                0, 0, false);

                            gameFactory.updateGame(externalGameStorage);
                            gameFactory.updateGameGrade(incomingGameId);

                            gameFactory.removeDesignersFromGame(externalGameStorage.id);
                            foreach (XElement designer in boardgame.Elements("boardgamedesigner"))
                            {
                                gameFactory.updateDesigner(int.Parse(designer.FirstAttribute.Value), designer.Value);
                                gameFactory.addDesignerToGame(int.Parse(designer.FirstAttribute.Value), externalGameStorage.id);
                            }

                            gameFactory.removePublishersFromGame(externalGameStorage.id);
                            foreach (XElement publisher in boardgame.Elements("boardgamepublisher"))
                            {
                                gameFactory.updatePublisher(int.Parse(publisher.FirstAttribute.Value), publisher.Value, string.Empty);
                                gameFactory.addPublisherToGame(int.Parse(publisher.FirstAttribute.Value), externalGameStorage.id);
                            }

                            foreach (XElement element in boardgame.Elements("name").Where(c => c.Attribute("primary") == null))
                                names.Add(element.Value);

                            gameFactory.removeGameNames(incomingGameId);

                            foreach (string name in names)
                                if (name != null && name.Length > 0)
                                    gameFactory.addGameName(incomingGameId, name);

                            return true;
                        }
                        catch (Exception)
                        {

                            retry--;
                            if (retry < 0)
                                return false;
                        }
                    }

                }

                return false;
            }
            catch (Exception ex)
            {
                throw (new Exception(this.ToString() + ".addBoardgameToDatabase : " + ex.Message, ex));
            }
        }

そして、さらに一歩進んだ addBoardgameToDatabase をトリガーするメソッドを取得しました。

private void StartThreadToHandleXmlFile(int gameId)
        {
            FileInfo fileInfo;
            XDocument xmlDoc;
            Boolean gameAdded = false;
            GameFactory gameFactory = new GameFactory();

            try
            {
                fileInfo = new FileInfo(_directory + "\\" + gameId.ToString() + ".xml");

                if (fileInfo.Exists)
                {
                    xmlDoc = XDocument.Load(fileInfo.FullName);

                    if (addBoardgameToDatabase(xmlDoc.Element("boardgames").Element("boardgame"), gameFactory))
                    {
                        gameAdded = true;
                        fileInfo.Delete();
                    }
                    else
                        return;
                }

                if (!gameAdded)
                {
                    gameFactory.InactivateGame(gameId);
                    fileInfo.Delete();
                }
            }
            catch (Exception)
            { throw; }
            finally
            {
                if(gameFactory != null)
                    gameFactory.CloseConnection();
            }
        }

そして最後にトップレベル:

public void UpdateGames(string directory)
{
    DirectoryInfo dirInfo;
    FileInfo fileInfo;
    Thread thread;

    int gameIdToStartOn = 1;

    dirInfo = new DirectoryInfo(directory);
    if(dirInfo.Exists)
    {
        _directory = directory;
        fileInfo = dirInfo.GetFiles("*.xml").OrderBy(c=> int.Parse(c.Name.Replace(".xml",""))).FirstOrDefault();

        gameIdToStartOn = int.Parse(fileInfo.Name.Replace(".xml", ""));

        for (int gameId = gameIdToStartOn; gameId < 500000; gameId++) 
        {
            try
            { StartThreadToHandleXmlFile(gameId); }
            catch(Exception){}
        }
    }
}
4

1 に答える 1

0
  1. 接続文字列に「Pooling=true」を追加して、SQL 接続プールを使用します。
  2. 接続とファイルを適切に閉じていることを確認してください。
  3. 1 つの大きなクエリを作成して 1 回だけ実行することができます。60.000 の緩やかなクエリよりもはるかに高速だと思います。

あなたのコードを少し見せてもらえますか?

于 2013-01-03T18:41:59.053 に答える