Wenn ich versuche, über ASP.NET online eine Verbindung zur MSSQL-Datenbank herzustellen, wird Folgendes angezeigt, wenn zwei oder mehr Personen gleichzeitig eine Verbindung herstellen:
ExecuteReader erfordert eine offene und verfügbare Verbindung. Der aktuelle Status der Verbindung lautet Verbinden.
Die Site funktioniert gut auf meinem localhost-Server.
Dies ist der grobe Code.
public Promotion retrievePromotion()
{
int promotionID = 0;
string promotionTitle = "";
string promotionUrl = "";
Promotion promotion = null;
SqlOpenConnection();
SqlCommand sql = SqlCommandConnection();
sql.CommandText = "SELECT TOP 1 PromotionID, PromotionTitle, PromotionURL FROM Promotion";
SqlDataReader dr = sql.ExecuteReader();
while (dr.Read())
{
promotionID = DB2int(dr["PromotionID"]);
promotionTitle = DB2string(dr["PromotionTitle"]);
promotionUrl = DB2string(dr["PromotionURL"]);
promotion = new Promotion(promotionID, promotionTitle, promotionUrl);
}
dr.Dispose();
sql.Dispose();
CloseConnection();
return promotion;
}
Darf ich wissen, was möglicherweise schief gelaufen ist und wie ich das Problem beheben kann?
Bearbeiten: Nicht zu vergessen, meine Verbindungszeichenfolge und Verbindung sind beide statisch. Ich glaube das ist der Grund. Bitte beraten.
public static string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
public static SqlConnection conn = null;
c#
.net
sql-server
ado.net
database-connection
Guo Hong Lim
quelle
quelle
conString
nichts zur Leistung beiträgt, da sie sowieso standardmäßig zwischengespeichert wird (wie jeder Konfigurationswert für die aktuelle Anwendung).Antworten:
Es tut mir leid, dass ich erst einmal kommentiert habe, aber ich poste fast jeden Tag einen ähnlichen Kommentar, da viele Leute denken, dass es klug wäre, die ADO.NET-Funktionalität in eine DB-Klasse zu kapseln (ich auch vor 10 Jahren). Meistens entscheiden sie sich für statische / gemeinsam genutzte Objekte, da dies schneller zu sein scheint als das Erstellen eines neuen Objekts für eine Aktion.
Das ist weder in Bezug auf die Leistung noch in Bezug auf die Ausfallsicherheit eine gute Idee.
Wildern Sie nicht auf dem Territorium des Verbindungspools
Es gibt einen guten Grund, warum ADO.NET die zugrunde liegenden Verbindungen zum DBMS im ADO-NET-Verbindungspool intern verwaltet :
Es gibt also offensichtlich keinen Grund, das Erstellen, Öffnen oder Schließen von Verbindungen zu vermeiden, da diese überhaupt nicht erstellt, geöffnet und geschlossen werden. Dies ist "nur" ein Flag, mit dem der Verbindungspool weiß, wann eine Verbindung wiederverwendet werden kann oder nicht. Aber es ist ein sehr wichtiges Flag, denn wenn eine Verbindung "in Gebrauch" ist (der Verbindungspool geht davon aus), muss eine neue physische Verbindung zum DBMS geöffnet werden, was sehr teuer ist.
Sie erzielen also keine Leistungsverbesserung, sondern das Gegenteil. Wenn die angegebene maximale Poolgröße (100 ist die Standardeinstellung) erreicht ist, erhalten Sie sogar Ausnahmen (zu viele offene Verbindungen ...). Dies wirkt sich also nicht nur enorm auf die Leistung aus, sondern ist auch eine Quelle für böse Fehler und (ohne Verwendung von Transaktionen) ein Daten-Dumping-Bereich.
Wenn Sie sogar statische Verbindungen verwenden, erstellen Sie eine Sperre für jeden Thread, der versucht, auf dieses Objekt zuzugreifen. ASP.NET ist von Natur aus eine Multithreading-Umgebung. Es gibt also eine große Chance für diese Sperren, was bestenfalls zu Leistungsproblemen führt. Früher oder später erhalten Sie viele verschiedene Ausnahmen (wie Ihr ExecuteReader eine offene und verfügbare Verbindung benötigt ).
Fazit :
using-statement
, um (bei Verbindungen) implizit zu entsorgen und zu schließenDies gilt nicht nur für Verbindungen (obwohl dies am auffälligsten ist). Jedes Objekt, das implementiert wird,
IDisposable
sollte entsorgt werden (am einfachsten vonusing-statement
), umso mehr imSystem.Data.SqlClient
Namespace.All dies spricht gegen eine benutzerdefinierte DB-Klasse, die alle Objekte kapselt und wiederverwendet. Das ist der Grund, warum ich kommentiert habe, es zu verwerfen. Das ist nur eine Problemquelle.
Bearbeiten : Hier ist eine mögliche Implementierung Ihrer
retrievePromotion
Methode:quelle
Ich habe diesen Fehler vor ein paar Tagen entdeckt.
In meinem Fall lag es daran, dass ich eine Transaktion für einen Singleton verwendet habe.
.Net funktioniert nicht gut mit Singleton, wie oben angegeben.
Meine Lösung war folgende:
Ich habe HttpContext.Current.Items für meine Instanz verwendet. Diese Klasse DbHelper und DbHelperCore ist meine eigene Klasse
quelle