2009-05-06 9 views
1

Erstmaliger Benutzer von Stackoverflow, aber ich habe seine Entwicklung über Coding Horror verfolgt.Die Eigenschaft 'ConnectionString' konnte nicht geändert werden. Der aktuelle Zustand der Verbindung ist offen

Ich habe massive Kopfschmerzen mit dem obigen Fehler. Ich habe ELMAH installiert und Google Analytics und da der Seitenverkehr zugenommen hat, habe ich die Anzahl der Male gesehen, in denen ich diesen Fehler gesehen habe.

Ich habe mein Bestes getan, um den Microsoft-Prinzipien zu folgen: http://msdn.microsoft.com/en-us/library/ms971481.aspx während der Entwicklung und ich habe meinen Code so weit wie möglich optimiert, basierend auf mehreren Quellen der Beratung im Internet.

Ich habe meine SqlConnection in einer öffentlichen Klasse;

Public Class pitstop 
Public Shared oConn As New System.Data.SqlClient.SqlConnection 
    Public Shared Sub doConnect() 
    If oConn.State = ConnectionState.Closed Then 
     oConn.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString 
     oConn.Open() 
    End If 
End Sub 
Public Shared Sub doGarbage() 
    oConn.Dispose() 
End Sub 
' /// other code /// 
End Class 

Und in meinem Haupt-Anwendungsseiten, muss ich sehr ähnlich wie diese:

Private Sub doPump() 
    pitstop.doConnect() 
    Dim cmd As New System.Data.SqlClient.SqlCommand("doGetCategory", pitstop.oConn) 
    Dim dt As New DataTable 
    Dim dr As SqlDataReader 

    cmd.Parameters.Add("@cat", SqlDbType.Int) 
    cmd.Parameters("@cat").Value = CType(Request.QueryString("id"), Integer) 

    cmd.CommandType = CommandType.StoredProcedure 

    dr = cmd.ExecuteReader() 
    While dr.Read() 
     If dr.HasRows = True Then 
      litCategory.Text = dr("category") 
      litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc")) 
     End If 
    End While 
    cmd = Nothing 
    dr.Close() 
    pitstop.doGarbage() 
End Sub 

ich diese Methode überall verwendet haben und die meiste Zeit gut es funktioniert, aber jetzt ist die Website die Dramen haben begonnen, entsetzlich beschäftigt zu sein! Hat jemand irgendwelche Ideen?

Ich würde es vorziehen, Berge von Code nicht neu schreiben zu müssen, aber ich bin offen für Vorschläge.

:)

Chris

Antwort

7

Ihre Verbindungen zu teilen, ist das Problem.

Es besteht keine Notwendigkeit, Verbindungen zu teilen und Probleme zu verursachen, wie Sie gerade erleben. .net Verbindungspooling behandelt die Freigabe der real Verbindungen hinter den Kulissen.

einfach eine neue Verbindung in doPump()

Private Sub doPump() 
    Using Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString) 
     Using Dim cmd As New SqlCommand("doGetCategory", conn) 
     cmd.CommandType = CommandType.StoredProcedure 
     cmd.Parameters.AddWithValue("@cat", CType(Request.QueryString("id"), Integer)) 
     conn.Open() 
     Using Dim dr as SqlDataReader = cmd.ExecuteReader() 
      While dr.Read() 
        litCategory.Text = dr("category") 
        litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc")) 
      End While 
      dr.Close() 
     End Using 
    End Using 
End Sub 
+0

+1 für mich es :-) –

1

Es gibt so viele Probleme mit Ihrem Code erstellen, weiß ich nicht wirklich, wo ich anfangen.

Zunächst einmal nehme ich an, dass pitstop ist tatsächliche Klassenname, die eine schreckliche ist. Zweitens, pitstop.doMakeReadyForHTML lässt mich denken, dass diese Klasse alle Arten von Funktionalität enthält, die nicht wirklich dorthin gehört.

Drittens und am schrecklichsten ist, dass Ihr SqlConnection Objekt Shared ist. Und das ist in einer Web-App, die von Natur aus Multithread ist.

Viertens befindet sich Ihre Datenbankzugriffslogik in Ihrer Code-Behind-Seite, die schlecht ist.

Fünftens verwalten Sie Ihre Ressourcen nicht richtig. Was passiert, wenn eine Ausnahme vor dem Aufruf an pitstop.doGarbage() (schrecklicher Name, übrigens) auftritt? Die Verbindung wird entweder nie geschlossen, oder sie hängt herum und verursacht alle Arten von Fehlern.

Was ich vorschlagen, ist wie folgt. Informieren Sie sich über design patterns und software architecture im Allgemeinen. Dann werden Sie alle Ihre Probleme selbst sehen. Als nächstes gehen Sie lesen Patterns of Enterprise Application Architecture: Dies wird Ihnen eine solide Grundlage zu bauen auf.

So weit wie Ihr aktueller Code geht: un Shared Ihre Verbindung, verschieben Sie Ihre Datenzugriffslogik in eine separate Klasse, Ressourcen ordnungsgemäß verwalten (Think Using Anweisung).

+0

Danke, Deviant und Anton zu schlagen. Mein Code ist ein Chaos :(Aber ich habe in die richtige Richtung gesetzt :) Danke. Ich werde es hier überprüfen, ändern und posten. Danke noch einmal. – dooburt

+0

Chris: Der dritte und der fünfte Punkt sind die, die am unmittelbarsten auf die Frage zutreffen, die du fragst, und auf diejenigen, die du weiterverfolgen solltest. –

+0

+1 für das Hinzufügen einiger hilfreicher Vorschläge. –

0

Ich habe den folgenden Code hinzugefügt, der die 'gemeinsame' Verbindung aus der Boxenstopp-Klasse entfernt hat. Pitstop heißt "Boxenstopp", denn das ist der Name des Projekts. Ist es ungeeignet? Welche Konventionen benutzt ihr?

Ich habe die DoGarbage() -Funktion verschrottet und jetzt die Verbindung und Disposable "Inline" aufrufen, so;

Private Sub doPump() 
    Dim oConn As New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("pitstopConnectionString").ConnectionString) 
    Dim cmd As New System.Data.SqlClient.SqlCommand("doGetCategory", oConn) 
    oConn.Open() 

    Dim dt As New DataTable 
    Dim dr As SqlDataReader 

    cmd.Parameters.Add("@cat", SqlDbType.Int) 
    cmd.Parameters("@cat").Value = CType(Request.QueryString("id"), Integer) 

    cmd.CommandType = CommandType.StoredProcedure 

    dr = cmd.ExecuteReader() 
    While dr.Read() 
     If dr.HasRows = True Then 
      litCategory.Text = dr("category") 
      litCategoryDesc.Text = pitstop.doMakeReadyForHTML(dr("desc")) 
     End If 
    End While 
    cmd = Nothing 
    dr.Close() 

    oConn.Dispose() 
End Sub 

Ist das korrekt?

Darüber hinaus erwähnte Anton die Funktionalität innerhalb der Klasse als inkorrekt - ich werde die Dokumente lesen, die er verlinkt hat - aber gibt es eine schnelle Antwort, warum es falsch ist?

Vielen Dank an alle Antworten - Sie waren alle sehr hilfreich.

Chris

+0

Ich habe meinen Code so aktualisiert, wie Sie es machen möchten. Sorry, wenn es kleinere Syntaxfehler gibt, habe ich VB seit Jahren nicht mehr gemacht. aber so würde ich es in C# machen. Sie müssen Ihre IDisposable-Objekte (SqlConnection, SqlCommand usw.) in Using Statements einschließen. http://msdn.microsoft.com/en-us/library/htd05whh(VS.80).aspx –

+0

Dank Deviant, atemberaubende Beispiele. Du warst eine große Hilfe. Danke vielmals. – dooburt