我有客户端 - 服务器应用程序,其中服务器端是Azure WCF服务,其中包含SQL azure数据库中的数据。客户端是Windows Phone 7 Silverlight应用程序。客户端和服务器通过WCF进行通信。服务器向客户端提供存储在Azure SQL数据库中的数据。
我最近遇到了一些池化问题。每次客户请求到达时我都在创建新对象。我没有关闭这个连接,很快就遇到了异常:
超时已过期。在获得a之前经过了超时时间 从游泳池连接。这可能是因为所有人都集中了 正在使用连接并达到最大池大小。
我的问题是 - 如何处理与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();
}
}
答案 0 :(得分:1)
默认情况下,池连接是SQL连接。因此,您应该在需要时“创建”它们并在完成后将其销毁。 (如果您使用using
而非try/finally
,则代码会更简单。)
答案 1 :(得分:0)
您在代码中指的是connection
两次,因此您有两个不同的连接,因为您的get
总是会创建一个新连接!
因此,后者被创建然后立即处理,但前一个没有关闭。
至少重写您的代码:
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();
}
}
答案 2 :(得分:0)
问题在于您没有关闭用于命令的连接,而是关闭了为关闭它而创建的新连接。
execute
方法的正文应如下所示:
var con = connection;
try
{
SqlCommand com = new SqlCommand(query, con);
com.ExecuteNonQuery();
}
finally
{
con.Close();
}
答案 3 :(得分:0)
每个请求一个连接的连接太多了。 (一个极端) 单例连接的连接太少了。
您需要的是每个用户会话建立一个连接。 最简单的方法是使用IoC容器,如Ninject,并通过容器请求连接。
答案 4 :(得分:0)
我同意奥利弗的意见,你应该建立联系并每次关闭它们;连接池将为您处理剩下的事情。此外,您应该保持您的连接开放到最短的时间。每次关闭您的连接,并尽可能快地确保您的连接字符串是相同的,确保您的连接池策略能够正常工作。
答案 5 :(得分:0)
我同意Wiktor Zychla,Tobias和Herve Roggero提供的答案。他们解释说:
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();
}
}