在多线程服务器应用程序中访问SQL DB

问题描述:

在我的服务器应用程序中,我想使用DB(SQL Server),但我很不确定最好的方法。有客户的请求来到线程池,因此他们的处理是异步的。每个请求通常需要读取或写入数据库,所以我在考虑创建连接,执行查询并返回结果的静态方法。我只是害怕打开和关闭连接是否不太慢,以及是否无法达到某些连接限制?这是一个好方法吗?在多线程服务器应用程序中访问SQL DB

惊讶的是,没有人提到连接池。如果你认为你会有大量的请求,为什么不设置一个池的最小池大小设置为25(这里的任意数字,不要拍摄)和最大池大小设置为200. 这将减少连接尝试的次数,并确保如果你没有泄漏连接句柄(你应该明确注意不要发生的事情),你将永远有一个等待你的连接。 关于连接池的参考文章:http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx 另一方面说明,为什么需要在代码中包含连接字符串?为了可维护性,将其设置在web.config或app.config中。我不得不“修复”那些做过这些事情的代码,而且我总是对负责这些事情的程序员发誓。

+0

谢谢。也有连接打开(在字符串中指定池)的静态方法就足够了?然后我会从不同的线程调用这个静态方法。 – Thomas 2010-02-20 11:27:21

+0

是的,这将是相当不错的。池化方法是我用entlib进行非常简单的数据访问。我建议这也是你应该考虑的事情。它使得数据访问比代码中的更容易。 – chiefbrownbotom 2010-02-20 22:33:54

我有和你一样的问题。有巨大的应用程序,我开始制作多线程。将一个连接打开并重新使用的好处是,您可以多次请求数据库以获取数据,因为可以根据请求生成新的连接(无需等待其他线程完成获取数据),并且例如您无法连接到sql(当网络出现故障时可能会发生一两次),无论如何您都必须始终检查连接是否打开。

这是我在MS SQL中获取数据库行的代码,但其他的东西应该以完全相同的方式完成。请记住,sqlConnectOneTime(字符串varSqlConnectionDetails)在没有连接时存在返回null的缺陷,因此需要根据需要进行一些修改,否则如果sql无法建立连接,查询将失败。你只需要添加适当的代码:-)希望处理有这将是对您有用:-)

public const string sqlDataConnectionDetails = "Data Source=SQLSERVER\\SQLEXPRESS;Initial Cata...."; 

    public static string sqlGetDatabaseRows(string varDefinedConnection) { 
     string varRows = ""; 
     const string preparedCommand = @" 
        SELECT SUM(row_count) AS 'Rows' 
        FROM sys.dm_db_partition_stats 
        WHERE index_id IN (0,1) 
        AND OBJECTPROPERTY([object_id], 'IsMsShipped') = 0;"; 
     using (var varConnection = Locale.sqlConnectOneTime(varDefinedConnection)) 
     using (var sqlQuery = new SqlCommand(preparedCommand, varConnection)) 
     using (var sqlQueryResult = sqlQuery.ExecuteReader()) 
      while (sqlQueryResult.Read()) { 
       varRows = sqlQueryResult["Rows"].ToString(); 
      } 
     return varRows; 
    } 


    public static SqlConnection sqlConnectOneTime(string varSqlConnectionDetails) { 
     SqlConnection sqlConnection = new SqlConnection(varSqlConnectionDetails); 
     try { 
      sqlConnection.Open(); 
     } catch (Exception e) { 
      MessageBox.Show("Błąd połączenia z serwerem SQL." + Environment.NewLine + Environment.NewLine + "Błąd: " + Environment.NewLine + e, "Błąd połączenia"); 
     } 
     if (sqlConnection.State == ConnectionState.Open) { 
      return sqlConnection; 
     } 
     return null; 
    } 

摘要:

定义一个全局变量与SQL Server的ConnectionDetails

一全局方法进行连接(您需要处理空值)

使用using来处理连接,sql查询以及完成读/写/更新方法时的所有内容。

+0

这实际上不起作用......如果您尝试使用连接第二次,您会发现它无法使用,因为它已被放置在顶部的末尾,使用{}块 – Rob 2010-02-20 09:47:36

+0

它会在我使用它时起作用。我每隔几秒调用一次sqlGetDatabaseRows,并按设计工作。我不想第二次使用连接。我开始的方法,它连接到SQL,当它与SQL查询完成它关闭连接和处置一切。下次您需要查询数据库时,您将不得不再次连接。我在每个需要连接到sql的方法中打开新的连接。 – MadBoy 2010-02-20 09:54:16

+0

@Rob你能解释为什么你认为我的例子很糟糕吗?它按照http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx文章中的建议打开Using内部的连接。它返回到池中,如果需要可以重新使用。 – MadBoy 2010-02-20 12:15:47

你还没有告诉我们的一件事,那么给你一个适合你的答案是有用的你期望你的服务器应用程序的负载水平为

对于上述问题的答案几乎都是,但答案是你不应该担心。 ADO.net/Sql Server提供的连接池可以消除从每个“var c = new SqlConnection(connectionString)”调用创建连接的一些开销。

+0

此外,我可以有查询参数的静态方法,并从不同的线程调用它,因为连接将汇集? – Thomas 2010-02-20 11:03:11

恕我直言,最好的办法是依靠ADO.NET连接池机制,而不要尝试手动处理数据库连接。写下您的数据访问方法是这样的:

public void SomeMethod() 
{ 
    using (var connection = new SqlConnection(connectionString)) 
    using (var command = connection.CreateCommand()) 
    { 
     connection.Open(); 
     command.CommandText = "SELECT Field1 FROM Table1"; 
     using (var reader = command.ExecuteReader()) 
     { 
      while(reader.Read()) 
      { 
       // do something with the results 
      } 
     } 
    } 
} 

然后就可以调用无论你喜欢这种方法,使其静态的,从任何线程调用它。请记住,在连接上调用Dispose不会实际关闭它。它会将其返回到连接池,以便它可以重新使用。