C# ASP.NET应用程序中的SQL Server连接

C# ASP.NET应用程序中的SQL Server连接,c#,asp.net,sql-server,C#,Asp.net,Sql Server,我用asp.net创建了一个web应用程序,大约有100个用户在使用它 然而,人们不时收到连接仍然打开的错误消息。表示未正确关闭 它出现在随机的地方,而不是一个特定的地方,之前没有其他错误 public static SqlConnection conn = new SqlConnection("Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0"); pr

我用
asp.net
创建了一个web应用程序,大约有
100个用户在使用它

然而,人们不时收到连接仍然打开的错误消息。表示未正确关闭

它出现在随机的地方,而不是一个特定的地方,之前没有其他错误

public static SqlConnection conn = new SqlConnection("Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0");

private void populateGameDrop()
{
    try
    {
        conn.Open();
        drop_game.Items.Clear();

        SqlCommand cmd = conn.CreateCommand();
        Access ac = (Access)Session["Access"];
        cmd.CommandText = "Select * from dbo.Games where " + ac.GameQuery;

        SqlDataReader r = cmd.ExecuteReader();

        while (r.Read())
        {
            drop_game.Items.Add(new ListItem(r["name"].ToString(), r["Abbr"].ToString()));
        }

        conn.Close();
    }
    catch (Exception exc)
    {
        conn.Close();
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }

    populateServers();
    SetSplitScreen();
}
我知道,当我的应用程序中有一个bug,并且它在我没有优雅地处理错误的情况下崩溃时,连接也会保持打开状态,基本上每个人都会因此崩溃。这让我想到,每个人都使用相同的连接对象,是否有可能两个用户拥有完美的时间,同时使用
DB connection
调用函数,从而导致错误?有没有办法确保每个人都使用自己的连接对象,比如将其放在会话中或其他什么

我希望你能理解我的意思,我不认为发布我的任何代码会有帮助,因为它发生在我的项目中随机的地方

它们使用
System.Data.SqlClient
连接到
SQL Server

在下面查找生成错误的函数。此函数由页面加载调用,前面没有任何内容

public static SqlConnection conn = new SqlConnection("Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0");

private void populateGameDrop()
{
    try
    {
        conn.Open();
        drop_game.Items.Clear();

        SqlCommand cmd = conn.CreateCommand();
        Access ac = (Access)Session["Access"];
        cmd.CommandText = "Select * from dbo.Games where " + ac.GameQuery;

        SqlDataReader r = cmd.ExecuteReader();

        while (r.Read())
        {
            drop_game.Items.Add(new ListItem(r["name"].ToString(), r["Abbr"].ToString()));
        }

        conn.Close();
    }
    catch (Exception exc)
    {
        conn.Close();
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }

    populateServers();
    SetSplitScreen();
}

您的
SQL
连接不应该是静态的,请使用以下方法创建它们

var connectionString = "YOUR CONNECTION STRING";
var queryString = "SQL QUERY";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader dateReader = command.ExecuteReader()) {

}
非常重要

您应该使用参数化的
SQL
您的代码会受到
SQL
注入攻击


请参见您的
SQL
连接不应该是静态的,请使用以下方法创建它们

var connectionString = "YOUR CONNECTION STRING";
var queryString = "SQL QUERY";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader dateReader = command.ExecuteReader()) {

}
非常重要

您应该使用参数化的
SQL
您的代码会受到
SQL
注入攻击


请参见您的
SQL
连接不应该是静态的,请使用以下方法创建它们

var connectionString = "YOUR CONNECTION STRING";
var queryString = "SQL QUERY";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader dateReader = command.ExecuteReader()) {

}
非常重要

您应该使用参数化的
SQL
您的代码会受到
SQL
注入攻击


请参见您的
SQL
连接不应该是静态的,请使用以下方法创建它们

var connectionString = "YOUR CONNECTION STRING";
var queryString = "SQL QUERY";

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(queryString, connection))
using (SqlDataReader dateReader = command.ExecuteReader()) {

}
非常重要

您应该使用参数化的
SQL
您的代码会受到
SQL
注入攻击


请参见不要尝试共享
SqlConnection
对象

请尝试以下方法:

private static string connString = "Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0";
private void populateGameDrop()
{
    try
    {
        using (var conn = new SqlConnection(connString))
        {
            conn.Open();
            drop_game.Items.Clear();
            using (var cmd = conn.CreateCommand())
            {
                Access ac = (Access)Session["Access"];
                //TODO
                //TODO - Introduce parameters to avoid SQL Injection risk
                //TODO
                cmd.CommandText = "Select name,Abbr from dbo.Games where " + ac.GameQuery;
                using(SqlDataReader r = cmd.ExecuteReader())
                {
                    while (r.Read())
                    {
                        drop_game.Items.Add(new ListItem(r["name"].ToString(),
                                            r["Abbr"].ToString()));
                    }
                }
            }
        }
    }
    catch (Exception exc)
    {
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }
    populateServers();
    SetSplitScreen();
}

在幕后,.NET使用了一个名为的概念,以便将到SQL Server的实际连接数降至最低。但是
SqlConnection
对象不是为多线程共享而设计的。

不要尝试共享
SqlConnection
对象

请尝试以下方法:

private static string connString = "Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0";
private void populateGameDrop()
{
    try
    {
        using (var conn = new SqlConnection(connString))
        {
            conn.Open();
            drop_game.Items.Clear();
            using (var cmd = conn.CreateCommand())
            {
                Access ac = (Access)Session["Access"];
                //TODO
                //TODO - Introduce parameters to avoid SQL Injection risk
                //TODO
                cmd.CommandText = "Select name,Abbr from dbo.Games where " + ac.GameQuery;
                using(SqlDataReader r = cmd.ExecuteReader())
                {
                    while (r.Read())
                    {
                        drop_game.Items.Add(new ListItem(r["name"].ToString(),
                                            r["Abbr"].ToString()));
                    }
                }
            }
        }
    }
    catch (Exception exc)
    {
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }
    populateServers();
    SetSplitScreen();
}

在幕后,.NET使用了一个名为的概念,以便将到SQL Server的实际连接数降至最低。但是
SqlConnection
对象不是为多线程共享而设计的。

不要尝试共享
SqlConnection
对象

请尝试以下方法:

private static string connString = "Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0";
private void populateGameDrop()
{
    try
    {
        using (var conn = new SqlConnection(connString))
        {
            conn.Open();
            drop_game.Items.Clear();
            using (var cmd = conn.CreateCommand())
            {
                Access ac = (Access)Session["Access"];
                //TODO
                //TODO - Introduce parameters to avoid SQL Injection risk
                //TODO
                cmd.CommandText = "Select name,Abbr from dbo.Games where " + ac.GameQuery;
                using(SqlDataReader r = cmd.ExecuteReader())
                {
                    while (r.Read())
                    {
                        drop_game.Items.Add(new ListItem(r["name"].ToString(),
                                            r["Abbr"].ToString()));
                    }
                }
            }
        }
    }
    catch (Exception exc)
    {
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }
    populateServers();
    SetSplitScreen();
}

在幕后,.NET使用了一个名为的概念,以便将到SQL Server的实际连接数降至最低。但是
SqlConnection
对象不是为多线程共享而设计的。

不要尝试共享
SqlConnection
对象

请尝试以下方法:

private static string connString = "Data Source=Server00\\SQLEXPRESS;Initial Catalog=r2;Integrated Security=true;Connect Timeout=0";
private void populateGameDrop()
{
    try
    {
        using (var conn = new SqlConnection(connString))
        {
            conn.Open();
            drop_game.Items.Clear();
            using (var cmd = conn.CreateCommand())
            {
                Access ac = (Access)Session["Access"];
                //TODO
                //TODO - Introduce parameters to avoid SQL Injection risk
                //TODO
                cmd.CommandText = "Select name,Abbr from dbo.Games where " + ac.GameQuery;
                using(SqlDataReader r = cmd.ExecuteReader())
                {
                    while (r.Read())
                    {
                        drop_game.Items.Add(new ListItem(r["name"].ToString(),
                                            r["Abbr"].ToString()));
                    }
                }
            }
        }
    }
    catch (Exception exc)
    {
        Log.Error(exc.ToString());
        Session["Error"] = exc.ToString();
        Response.Redirect("~/YouBrokeIt.aspx");
    }
    populateServers();
    SetSplitScreen();
}

在幕后,.NET使用了一个名为的概念,以便将到SQL Server的实际连接数降至最低。但是,
SqlConnection
对象不是为多线程共享而设计的。

不要将数据库代码直接放在ASPX页面中。创建额外的层(即DAL)允许您在不使用页面的情况下测试DB方法

试试这样的

//Don't embed database logic directly in the aspx files
public class GamesProvider
{        
    //Put the ConnectionString in you configuration file
    private string ConnectionString
    {
        get { return ConfigurationManager.ConnectionStrings["GameDB"].ConnectionString; }
    }

    public IEnumerable<Game> LoadGames(string x, string y)
    {
        var games = new List<Game>();

        const string queryString = "select name, Abbr from dbo.Games where x = @x and y = @y";

        using (var connection = new SqlConnection(ConnectionString))
        using (var command = new SqlCommand(queryString, connection))
        {
            command.Parameters.AddWithValue("@x", x);
            command.Parameters.AddWithValue("@y", y);
            using (var dateReader = command.ExecuteReader())
            {
                while (dateReader.Read())
                {
                    var game = new Game
                    {
                        Name = dateReader["name"].ToString(),
                        Abbr = dateReader["Abbr"].ToString(),
                    };
                    games.Add(game);
                }
            }
        }

        return games;
    }
}

//Use types
public class Game
{
    public string Name { get; set; }
    public string Abbr { get; set; }
}
//不要将数据库逻辑直接嵌入到aspx文件中
公共类游戏提供者
{        
//将ConnectionString放入配置文件中
私有字符串连接字符串
{
获取{return ConfigurationManager.ConnectionString[“GameDB”].ConnectionString;}
}
公共IEnumerable LoadGames(字符串x、字符串y)
{
var games=新列表();
const string queryString=“选择名称,缩写自dbo.Games,其中x=@x和y=@y”;
使用(var连接=新的SqlConnection(ConnectionString))
使用(var命令=新的SqlCommand(queryString,connection))
{
command.Parameters.AddWithValue(“@x”,x);
command.Parameters.AddWithValue(“@y”,y);
使用(var dateReader=command.ExecuteReader())
{
while(dateReader.Read())
{
var游戏=新游戏
{
Name=dateReader[“Name”]。ToString(),
Abbr=dateReader[“Abbr”].ToString(),
};
games.Add(游戏);
}
}
}
返回游戏;
}
}
//使用类型
公开课游戏
{
公共字符串名称{get;set;}
公共字符串Abbr{get;set;}
}

不要将数据库代码直接放在ASPX页面中。创建额外的层(即DAL)允许您在不使用页面的情况下测试DB方法

试试这样的

//Don't embed database logic directly in the aspx files
public class GamesProvider
{        
    //Put the ConnectionString in you configuration file
    private string ConnectionString
    {
        get { return ConfigurationManager.ConnectionStrings["GameDB"].ConnectionString; }
    }

    public IEnumerable<Game> LoadGames(string x, string y)
    {
        var games = new List<Game>();

        const string queryString = "select name, Abbr from dbo.Games where x = @x and y = @y";

        using (var connection = new SqlConnection(ConnectionString))
        using (var command = new SqlCommand(queryString, connection))
        {
            command.Parameters.AddWithValue("@x", x);
            command.Parameters.AddWithValue("@y", y);
            using (var dateReader = command.ExecuteReader())
            {
                while (dateReader.Read())
                {
                    var game = new Game
                    {
                        Name = dateReader["name"].ToString(),
                        Abbr = dateReader["Abbr"].ToString(),
                    };
                    games.Add(game);
                }
            }
        }

        return games;
    }
}

//Use types
public class Game
{
    public string Name { get; set; }
    public string Abbr { get; set; }
}
//不要将数据库逻辑直接嵌入到aspx文件中
公共类游戏提供者
{        
//将ConnectionString放入配置文件中
私有字符串连接字符串
{
获取{return ConfigurationManager.ConnectionString[“GameDB”].ConnectionString;}
}
公共IEnumerable LoadGames(字符串x、字符串y)
{
var games=新列表();
const string queryString=“选择名称,缩写自dbo.Games,其中x=@x和y=@y”;
使用(var连接=新的SqlConnection(ConnectionString))
使用(var命令=新的SqlCommand(queryString,connection))
{
command.Parameters.AddWithValue(“@x”,x);
command.Parameters.AddWithValue(“@y”,y);
我们