C# 在同一时间和同一连接调用多个SQL Server
我创建了全局静态类,它有一个C# 在同一时间和同一连接调用多个SQL Server,c#,web-services,sql-server-2008,C#,Web Services,Sql Server 2008,我创建了全局静态类,它有一个SqlConnection,如下代码所示: public class Globals { public static SqlConnection SqlDbConn; public static OpenConnection(String ConnString) { SqlDbConn = new SqlConnection(ConnString); SqlDbConn.Open();
SqlConnection
,如下代码所示:
public class Globals
{
public static SqlConnection SqlDbConn;
public static OpenConnection(String ConnString)
{
SqlDbConn = new SqlConnection(ConnString);
SqlDbConn.Open();
}
}
然后创建了web服务,它有多个功能
我的问题是:如何在所有函数中同时使用相同的连接(SqlDbConn
)?换句话说,有多个用户同时调用此web服务,web服务中的每个函数都使用相同的SqlDbConn
,这是真的吗?如果不是,为什么
最后,在web服务中,我使用此构造函数初始化连接:
public class Service1 : System.Web.Services.WebService
{
private static bool Initialized = false;
static string ConnString= @"Data Source=192.168.1.1\SQLEXPRESS;UID=sa;PWD=0000;Initial Catalog=DBName; MultipleActiveResultSets=true";
public Service1()
{
// This method called each function call
if (!Initialized )
{
Globals.OpenConnection(ConnString);
Initialized = true;
}
}
}
您应该在每次调用数据库时创建一个新的
SqlConnection
实例,并在调用完成后处置它。SqlConnection有一个池机制,可以为您创建和重用连接。处理单个连接对象上的每个调用可能会在异步操作上引发会话繁忙异常您应该在对数据库的每个调用上创建一个新的SqlConnection
实例,并在完成后处置它。SqlConnection有一个池机制,可以为您创建和重用连接。处理单个连接对象上的每个调用可能会在异步操作上引发会话繁忙异常在存在线程的情况下,您的代码可能是非常错误的,而且在任何情况下,它都是基础结构的一个糟糕副本,已经以有效的方式重用了物理连接
然而,您不需要太多更改就可以获得更好的方法
public class Globals
{
// Keep global just the connection string
// (albeit you could simply pass it every time)
public static string ConnString {get;set;};
// Change the OpenConnection method to return the SqlConnection created
public static SqlConnection OpenConnection()
{
SqlConnection cnn = new SqlConnection(ConnString);
cnn.Open();
return cnn;
}
}
.....
public class Service1 : System.Web.Services.WebService
{
private static bool Initialized = false;
public Service1()
{
// This method called each function call
if (!Initialized )
{
// Don't hard code the connectionstring details, read it from CONFIG
// See ConfigurationManager class....
string connectionString = ReadConnectionStringFromYourConfigFile()
Globals.ConnString = connectionString;
Initialized = true;
}
}
// An usage example of your Globals
public int GetDatabaseValue()
{
using(SqlConnection cn = Globals.OpenConnection())
{
.....
} // Here the connection will be closed and disposed also in case of exceptions...
}
}
在存在线程的情况下,您的代码可能是非常错误的,而且在任何情况下,它都是基础结构的一个糟糕副本,该基础结构已经能够以有效的方式重用物理连接 然而,您不需要太多更改就可以获得更好的方法
public class Globals
{
// Keep global just the connection string
// (albeit you could simply pass it every time)
public static string ConnString {get;set;};
// Change the OpenConnection method to return the SqlConnection created
public static SqlConnection OpenConnection()
{
SqlConnection cnn = new SqlConnection(ConnString);
cnn.Open();
return cnn;
}
}
.....
public class Service1 : System.Web.Services.WebService
{
private static bool Initialized = false;
public Service1()
{
// This method called each function call
if (!Initialized )
{
// Don't hard code the connectionstring details, read it from CONFIG
// See ConfigurationManager class....
string connectionString = ReadConnectionStringFromYourConfigFile()
Globals.ConnString = connectionString;
Initialized = true;
}
}
// An usage example of your Globals
public int GetDatabaseValue()
{
using(SqlConnection cn = Globals.OpenConnection())
{
.....
} // Here the connection will be closed and disposed also in case of exceptions...
}
}
在“原始”ADO.NET级别上处理连接和命令的公认最佳实践是始终根据需要尽可能晚地创建这些对象,并尽快再次释放它们。ADO.NET已经内置了一个非常复杂的连接池机制——没有必要试图超越这一行之有效的机制
为了确保正确处理对象,一般也接受使用(…){…}块将对象放入中,如下所示:
// define query as a string
string query = "SELECT ..... FROM ... WHERE ......";
// create connection and command in "using" blocks
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmd = new SqlCommand(conn, query))
{
// set up e.g. parameters for your SqlCommand
// open the connection, execute the query, close the connnection again
conn.Open();
// for a SELECT, use ExecuteReader and handle the reader (or use SqlDataAdapter to fill a DataTable)
// for UPDATE, INSERT, DELETE just use a ExecuteNonQuery() to run the command
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// handle the data from the reader
}
// close reader
rdr.Close();
}
conn.Close();
}
在“原始”ADO.NET级别上处理连接和命令的公认最佳实践是始终根据需要尽可能晚地创建这些对象,并尽快再次释放它们。ADO.NET已经内置了一个非常复杂的连接池机制——没有必要试图超越这一行之有效的机制
为了确保正确处理对象,一般也接受使用(…){…}
块将对象放入中,如下所示:
// define query as a string
string query = "SELECT ..... FROM ... WHERE ......";
// create connection and command in "using" blocks
using (SqlConnection conn = new SqlConnection(-your-connection-string-here-))
using (SqlCommand cmd = new SqlCommand(conn, query))
{
// set up e.g. parameters for your SqlCommand
// open the connection, execute the query, close the connnection again
conn.Open();
// for a SELECT, use ExecuteReader and handle the reader (or use SqlDataAdapter to fill a DataTable)
// for UPDATE, INSERT, DELETE just use a ExecuteNonQuery() to run the command
using (SqlDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// handle the data from the reader
}
// close reader
rdr.Close();
}
conn.Close();
}
我创建了全局静态类,它有SqlConnection,如下代码所示:“-这是您的第一个错误!你能解释一下原因吗?正如@MitchWheat所说,试图比你的基础设施更聪明是没有意义的好吧,那么我怎么能做到呢?”我创建了全局静态类,它有SqlConnection,如下代码所示:“-这是你的第一个错误!你能解释一下为什么吗?正如@MitchWheat所说,试图比你的基础设施更聪明是没有意义的好吧,那么我怎么能做到呢?我不习惯conn.Open();和conn.Close();而且效果很好!为什么?如果您使用SqlDataAdapter
,那么它将在需要时打开连接本身。.Close()
不是绝对需要的-通过使用(..{…}
块将其放入中,.NET运行时将为您完成这项工作(但我更喜欢自己明确地完成),我不使用conn.Open();和conn.Close();而且效果很好!为什么?如果您使用SqlDataAdapter
,那么它将在需要时打开连接本身。.Close()
不是绝对需要的-通过使用(..{…}
块将其放入中,.NET运行时将为您完成这项工作(但我更喜欢自己明确地完成)