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

Azure SQL-单个或多个数据库连接

SQL连接默认情况下是池连接。因此,你应该在需要的时候"创造"它们,并在完成后销毁它们。(如果使用using而不是try/finally,代码会更简单。)

我同意Wiktor Zychla、Tobias和Herve Roggero提供的答案。他们解释说:

  1. 您的getter(connect属性)不会返回您期望的原始SqlConnection,因此原始连接不会关闭
  2. 您应该在需要时创建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的观点,即每次都应该创建连接并关闭它们;连接池将为您处理其余部分。此外,你应该将你的连接保持在最短的时间内。每次都要尽快关闭连接,并确保连接字符串始终相同,这样可以确保连接池策略发挥作用。