我创建了一个asp.net
的网络应用程序,大约100 users
正在使用它。
然而,人们不时会收到连接仍然打开的错误消息。表明它没有正确关闭。
它出现在随机的地方,而不是一个特定的地方,也没有其他错误。
我知道当我在应用程序中出现错误并且在没有我优雅地处理错误的情况下崩溃时,连接仍然保持打开状态,基本上每个人都会因此而崩溃。这让我觉得每个人都使用相同的连接对象,2个用户是否可能拥有完美的计时并使用DB connection
同时调用函数导致错误?有没有办法确保每个人都使用自己的连接对象,比如把它放在会话中还是什么?
我希望你能理解我的意思,我不认为发布我的任何代码会有所帮助,因为它发生在我项目中的随机位置。
他们使用SQL Server
与System.Data.SqlClient
建立连接。
在下面找到生成错误的函数。该函数由Page_Load调用,之前没有任何内容。
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();
}
答案 0 :(得分:2)
请勿尝试共享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使用一个名为connection pooling的概念,以便最小化与SQL Server的真实连接的实际数量。但SqlConnection
个对象并未设计为由多个线程共享。
答案 1 :(得分:1)
不要将数据库代码直接放在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; }
}
答案 2 :(得分:0)
您的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
注入攻击开放。