Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Azure SQL-单数据库连接还是多数据库连接?_C#_.net_Sql_Azure_Azure Sql Database - Fatal编程技术网

C# Azure SQL-单数据库连接还是多数据库连接?

C# Azure SQL-单数据库连接还是多数据库连接?,c#,.net,sql,azure,azure-sql-database,C#,.net,Sql,Azure,Azure Sql Database,我有一个客户机-服务器应用程序,其中服务器端是Azure WCF服务,数据位于SQLAzure数据库中。客户端是Windows Phone 7 silverlight应用程序。客户端和服务器通过WCF进行通信。服务器正在向客户端提供存储在Azure SQL数据库中的数据 我最近遇到了一些池的问题。每次客户端请求到达时,我都在创建新对象。我没有关闭此连接,很快遇到异常: 超时已过期。获取数据之前经过的超时时间 来自池的连接。发生这种情况的原因可能是所有的 连接正在使用,已达到最大池大小 我的问题是

我有一个客户机-服务器应用程序,其中服务器端是Azure WCF服务,数据位于SQLAzure数据库中。客户端是Windows Phone 7 silverlight应用程序。客户端和服务器通过WCF进行通信。服务器正在向客户端提供存储在Azure SQL数据库中的数据

我最近遇到了一些池的问题。每次客户端请求到达时,我都在创建新对象。我没有关闭此连接,很快遇到异常:

超时已过期。获取数据之前经过的超时时间 来自池的连接。发生这种情况的原因可能是所有的 连接正在使用,已达到最大池大小

我的问题是-如何处理数据库的连接对象?我应该为每个客户机请求创建一个连接对象,还是应该创建处理对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();
            }
        }

您在代码中引用了两次
连接
,因此您有两个不同的连接,因为您的
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();
    }
} 

问题在于,您并没有关闭用于命令的连接,而是创建了一个新的连接来关闭它

execute
方法的主体应如下所示:

var con = connection;
try 
{ 
    SqlCommand com = new SqlCommand(query, con); 
    com.ExecuteNonQuery(); 
} 
finally 
{ 
    con.Close(); 
} 

每个请求一个连接就是连接太多。(一个极端) 单例连接太少了

您需要的是每个用户会话都有一个连接。
最简单的方法是使用IoC容器,如Ninject,并通过容器请求连接。

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

我同意Oliver的观点,您应该创建连接并每次关闭它们;连接池将为您处理其余的问题。此外,您还应将您的连接开放至最短时间。每次都尽可能快地关闭连接,并确保您的连接字符串在同一时间保持一致,确保您的连接池策略能够正常工作。

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

  • 您的getter(
    connect
    属性)不会返回您期望的原始
    SqlConnection
    ,因此原始连接不会关闭
  • 您应该在需要时创建
    SqlConnection
    s,只在需要时打开它们,完成后关闭它们
  • 这里有一个完整的解决方案:

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

    这是行不通的,因为
    连接的getter
    可能会抛出一个异常,然后
    c
    将是任何东西,这是编译器不喜欢的状态,原因很明显……对。检查很好。您仍然没有初始化
    c
    。并且局部变量不会自动设置为默认值,因此编译器仍然会抱怨在第一次尝试读取时,
    c
    没有被初始化的可能性(但是
    null
    的检查肯定不错)…我手头没有编译器,所以我做了一些基本的省略。现在我没有维护会话的机制。这种wcf通信更像是火与忘——每个请求都是独立的。来自一个客户端的请求之间的时间间隔可以在不到一秒到几分钟之间。如果我像上面描述的那样使用“using”,我不需要调用connection.close(),对吗?正确
    使用
    可以保证在连接超出范围()时调用
    connection.Close()。事实上,我对维克托的答案投了反对票,因为他的代码很糟糕!不过,他的观点是正确的。