Azure SQL-单个或多个数据库连接
本文关键字:数据库连接 SQL- 单个 Azure | 更新日期: 2023-09-27 18:21:53
我有客户端-服务器应用程序,其中服务器端是Azure WCF服务,数据在SQL Azure数据库中。客户端是Windows Phone 7 silverlight应用程序。客户端和服务器通过WCF进行通信。服务器正在向客户端提供存储在Azure SQL数据库中的数据。
我最近遇到了一些池化方面的问题。每次客户端请求到达时,我都在创建新对象。我没有关闭这个连接,很快就遇到了异常:
超时已过期。在获取来自池的连接。发生这种情况的原因可能是连接正在使用,已达到最大池大小。
我的问题是——应该如何处理到DB的连接对象?我应该为每个客户端请求创建一个连接对象,还是应该创建一个处理所有对db调用的singleton对象?这可能吗?连接对象不是在一段时间后超时吗?
我正在使用SQLConnection对象:
private static SqlConnection connection
{
get
{
SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder
{
DataSource = DB_SOURCE,
InitialCatalog = DB_NAME,
Encrypt = false,
TrustServerCertificate = false,
UserID = DB_USER,
Password = DB_PASS,
};
SqlConnection c = new SqlConnection(connectionStringBuilder.ToString());
c.Open();
return c;
}
}
public static void execute(String query)
{
try
{
SqlCommand com = new SqlCommand(query, connection);
com.ExecuteNonQuery();
}
finally
{
connection.Close();
}
}
SQL连接默认情况下是池连接。因此,你应该在需要的时候"创造"它们,并在完成后销毁它们。(如果使用using
而不是try/finally
,代码会更简单。)
我同意Wiktor Zychla、Tobias和Herve Roggero提供的答案。他们解释说:
- 您的getter(
connect
属性)不会返回您期望的原始SqlConnection
,因此原始连接不会关闭 - 您应该在需要时创建
SqlConnection
,只在需要时保持它们的打开状态,并在完成后关闭它们
这里有一个完整的解决方案:
private static string _connectionString = string.Empty;
private static string connectionString
{
get
{
if (string.IsNullOrEmpty(_connectionString))
{
_connectionString = new SqlConnectionStringBuilder
{
DataSource = DB_SOURCE,
InitialCatalog = DB_NAME,
Encrypt = false,
TrustServerCertificate = false,
UserID = DB_USER,
Password = DB_PASS,
}.ToString();
}
return _connectionString;
}
}
public static void Execute(String query)
{
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
每个请求一个连接太多了。(一个极端)Singleton连接太少了。
您需要的是每个用户会话都有一个连接。最简单的方法是使用IoC容器,如Ninject,并通过容器请求连接。
问题是您没有关闭用于命令的连接,而是创建了一个新的连接来关闭它。
execute
方法的主体应如下所示:
var con = connection;
try
{
SqlCommand com = new SqlCommand(query, con);
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
您在代码中引用了connection
两次,因此您有两个不同的连接,因为您的get
ter总是创建一个新的连接!
因此,后者被创建,然后立即被处理,但前者没有被关闭。
至少将代码重写为:
public static void execute(String query) {
SqlConnection c = null;
try {
c = connection;
using ( SqlCommand com = new SqlCommand(query, c);
com.ExecuteNonQuery();
}
finally {
if ( c!=null)
c.Close();
}
}
我同意Oliver的观点,即每次都应该创建连接并关闭它们;连接池将为您处理其余部分。此外,你应该将你的连接保持在最短的时间内。每次都要尽快关闭连接,并确保连接字符串始终相同,这样可以确保连接池策略发挥作用。