0

我在 C# 中运行一个循环,该循环在 Windows 8 64 位环境中读取文件并使用 MySQL ODBC 5.1 驱动程序更新 MySQL 数据库。

操作简单

  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参数是正确的

连接的打开和关闭是在永远循环的顶部方法中完成的(使用 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. 您可以创建一个大型查询并只执行一次,我认为它比 60.000 个松散查询快得多!

你能展示一下你的代码吗?

于 2013-01-03T18:41:59.053 回答