2011-12-10 31 views
0

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

我在某处看到有一个'threadpool'。真的吗?如果是这样,这是使用它的正确方法:

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"); 
     } 
    } 
} 

回答

4

我认为你在这里混淆了两种不同的资源;您可能确实需要为每个登录的玩家开放一个线程(实际上是一个进程),但这并不意味着您应该连接到每个玩家不断开放的数据库,因为数据库连接,文件句柄等操作不受管理资源,只要你完成它们就应该尽快解脱。

有一个很好的介绍和C#线程说明here

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

例如,您可以阅读更多关于此here的信息。微软还谈到了连接池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(); 

内侧载荷的,你可以调用的方法之一是PopulateFromDB(),这将包含上面的代码,并且将加载所有该用户的属性。您可能也有一个DAO类可以做同样的事情:

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

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

您可能会考虑查看某种形式的框架,比如ORM或类似的框架 - SO question has already been answered for MySql,而不是写很多这种数据访问逻辑。这也可以为您节省大量的时间和精力,并且可以让您专注于设计。

+0

所以,至少在短文中,上面的例子应该是我正在使用的? – will

+0

@是的,最重要的两个方面是USING语句,这意味着一旦你完成了unmanged资源就会被释放,并且SQL查询参数将从sql注入中为你的应用程序添加一层保护。我会在答案的底部添加一些关于如何在实践中使用它的例子。 – dash

+0

查询的参数化对许多数据库系统也有好处,因为它们也可以为参数化查询重用查询执行计划。 – dash