多线程环境中的mysql连接器

时间:2011-12-10 16:33:40

标签: c# mysql

我有一个连接到mysql服务器以获取数据的c#服务器。这个c#服务器是游戏的后端服务器,对于当前登录的每个玩家都有一个开放的线程。我如何进行mysql连接,每个线程的开放连接?对所有线程使用锁定的单个连接?

我在某处读到有一个'线程池'为了这。真的吗?如果是这样,这是使用它的正确方法:

using(var conn = new MySqlConnection(DatabaseHelper.getConnectionString()))
using (var cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "SELECT username FROM characters WHERE id=1";
    using (var reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
            user = reader.GetString("username");
        }
    }
}

1 个答案:

答案 0 :(得分:4)

我认为你在这里混淆了两种不同的资源;你可能确实希望每个登录的玩家都有一个开放的线程(实际上是一个进程),但这并不意味着你应该不断地为每个玩家打开数据库连接,因为数据库连接,文件句柄等都不会被管理资源,一旦你完成它们就应该被释放。

对C#threading here进行了很好的介绍和解释。

您应该只在需要时打开与数据库的连接。这意味着您的数据访问类可以多次实例化(这是最简单的设计),每个类都有自己的连接。如果你使用connection pooling,我觉得你可能一直在询问,那么你将会受益更多。转向静态数据库连接设计(其中许多人共享相同的dao类)可能会更成问题,因为您可能必须同步某些资源,确保某些变量只能通过锁定或类似方式按顺序访问,等等。

您可以阅读有关此here的更多信息。 Microsoft还谈到了连接池here的好处。

上面的代码是连接数据库的一个很好的起点,包括你正在关闭的using语句,并在你完成后立即处理连接;您可能还会考虑以下改进:

using(var conn = new MySqlConnection(DatabaseHelper.getConnectionString())) 
{
  using (var cmd = conn.CreateCommand()) 
  { 
      conn.Open(); 
      cmd.CommandType = CommandType.Text;
      //Parameterize your queries!
      cmd.CommandText = "SELECT username FROM characters WHERE id=?"; //Use ? as placeholder for parameters, and add parameters in the order they appear in your query.
      cmd.Parameters.Add(new MySqlParameter("@userid", MySqlDbType.Int, userid));

      using(IDataReader reader = cmd.ExecuteReader())
      { 
          //You should only expect one record. You might want to test for more than 1 record.
          if (reader.Read()) 
          { 
              user = reader.GetString(reader.GetOrdinal("username")); //Think also about null value checking.
          } 
      } 
  }
}

您可能拥有DAO类或用户类上的方法来执行此操作。例如,如果它是用户的方法,您可能会执行以下操作:

User myUser = new User(7);
myUser.Load(); 

在Load内部,您可能调用的方法之一是PopulateFromDB(),它将包含上面的代码,并将加载此用户的所有属性。您可能还有一个DAO类可以执行相同的操作:

UserLoader loader = new UserLoader();
string userName = loader.GetUserName(int userId);

将使用上面示例中的代码返回用户名。我更喜欢这种方法在类似User的类上,因为它在逻辑上与它连接。但是,您将冒着将DAO逻辑与用户业务逻辑混合的风险,这是一个独立的主题。

与其编写大量此类数据访问逻辑,您可能会考虑在某种形式的框架(如ORM或类似框架)上查看 - 这个question has already been answered for MySql在SO上。这也可以节省您大量的时间和精力,并且可以让您专注于设计。