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

时间:2012-01-29 18:10:43

标签: c# .net sql azure azure-sql-database

我有客户端 - 服务器应用程序,其中服务器端是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();
            }
        }

6 个答案:

答案 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提供的答案。他们解释说:

  1. 您的getter(connect属性)未返回您期望的原始SqlConnection,因此原始连接未关闭。
  2. 您应该在需要时创建SqlConnection,只在您需要时保持打开,并在完成后关闭它们。
  3. 这是一个完整的解决方案:

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