ODP.net Connection Pooling: ClientID Client-Id ändert sich nie vom ersten Benutzer, der sich anmeldet
Szenario: Wir haben eine Anwendung, die mithilfe von Oracle 10g und die neueste version von ODP.net innerhalb einer ASP.net -Anwendung. Nutzen wir die .ClientID WriteOnly-Eigenschaft auf das OracleConnection-Objekt übergeben, in einem bestimmten Benutzer-id der Datenbank, die für auditing-Zwecke. Wenn das Verbindungspooling deaktiviert ist, funktioniert dies problemlos.
Wenn es aktiviert ist, die erste person, die anmeldet (Beispiel: Benutzer1) aktualisiert einen Datensatz und die MODIFIED_BY USER1 ist, aber wenn ein anderer Benutzer den Köpfen in der website nach, so greifen die zusammengefasste Verbindung, die MODIFIED_BY ist immer noch Benutzer1 trotz übergabe USER2, um die ClientID.
Unserer Datenbank Logik ist wie folgt:
Verharren wir eine Klasse in einem ASP.net Sitzung hat unsere Datenbank Verbindung Logik in ihm. Auf den ersten Aufruf, dies ist unser Konstruktor:
Public Sub New(ByVal connection As String, Optional ByVal oracleClientID As String = "")
MyBase.New()
_oracleConnection = New OracleConnection(connection)
_clientID = oracleClientID
End If
End Sub
Hier ist der Kern der code zum öffnen und schließen, entsorgen:
Try
_OraCmd = New OracleCommand(command, _oracleConnection)
With _OraCmd
.BindByName = True
.Parameters.Clear()
.CommandType = CommandType.StoredProcedure
_oracleConnection.Open()
If _clientID <> "" Then _oracleConnection.ClientId = _clientID
Dim OraDadpt As New OracleDataAdapter(_OraCmd)
'' Logic to get data
OraDadpt.Fill(ds)
End With
Catch ex As Exception
Throw ex
Finally
ClearParameters()
_OraCmd.Dispose()
_oracleConnection.Close()
End Try
Der Gedanke ist, dass, da die Verbindung im Pool, es ist von einem angenommenen Anruf zu einem LOGON-Trigger, dass das nie passieren und die Client Id wird nie wieder gesetzt. Der ORACLE-Dokumentation, jedoch besagt, dass die ClientID verwendet wird, für genau das, was wir zu tun versuchen.
Hat jemand irgendwelche Gedanken auf, warum die SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') ist nicht festgelegt auf eine neue USERID übergeben wird, in die ClientID, wenn das Verbindungspooling verwendet wird, in unserem .NET-Anwendung mit ODP.net? Ist das eine Einstellung für Datenbank, listener Einstellung?
Update
Weitergeleitet haben wir die Frage zu Oracle. Dabei hatten wir erstellen eine kleine test-app, ahmte das Problem. Wenn Sie das tun, auf meinem localhost -- alles funktionierte perfekt mit Visual Studio integrierten Cassini-web-server. Mit IIS, die das Problem Auftritt.
UPDATE
Festgestellt, dass IIS nicht das problem. Es war Paket Variablen, die nicht ausgeglichen werden durch verbindungen, wurden gepoolt wiederverwendet werden, im wesentlichen, was die Bündelung tun soll. Wir lösten dieses Problem, indem mit DBMS_SESSION.MODIFY_PACKAGE_STATE(DBMS_SESSION.Neu INITIALISIEREN).
- Sie erwähnen die LOGON-trigger. Was genau ist die Aufgabe des LOGON-trigger in deinem setup? Und können Sie nach Ihrem code.
- So eine haben wir nicht. ODP.net sollte die Handhabung, über die .ClientID-Eigenschaft. Von allem, was ich gelesen habe, wenn die Anmeldung an der Datenbank passiert-ODP legt die SYS_CONTEXT mit der .ClientID.
- Ja, ODP.NET legt die SYS_CONTEXT. Aber das hat nichts zu tun mit einem LOGON-trigger, das ist etwas ganz anderes. Können Sie die Verbindungszeichenfolge, die Sie verwenden, die für das Verbindungspooling? Möglicherweise Sie sind nicht mit den ODP.NET connection-pool (das setzt die Client-ID, wenn die Verbindung an den pool zurückgegeben).
- Die Verbindungszeichenfolge ist einfach: "data source=dataSource;user id=user;password=pass;" - Pooling ist standardmäßig auf aus, was ich verstehe. Ich habe versucht mit alle Min-und Max-Pool-size Eigenschaften, etc mit kein Glück.
- Sie haben mein Beileid für oracle Hölle.
- Hey, Wie über die Einstellung DBMS_SESSION.SET_IDENTIFIER, wenn die Verbindung geöffnet wird
- Das ist es, was .ClientID soll in diesem Fall zu tun.
- verwenden Sie iis 6 oder 7 ? wenn 7 was ist Ihr Anwendungspool eingestellt ?
- Ist Ihr problem gelöst ?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Versuchen Sie es mit DBMS.Rest_Package vor dem schließen der verbindungen.
Das problem denke ich ist mit der Bündelung eingeschaltet ODP ist, halten Sie die Verbindung so, wie jeder Benutzer öffnet und schließt einen Zusammenhang mit den ODP-pooling ist, halten die session-Paket-Variablen im Speicher, bis die Verbindung mal aus. Jedoch, seit der Zeit,/und wieder-herstellen einer Verbindung von der Datenbank in den pool tritt nur auf, NACHDEM eine Verbindung an den pool ZURÜCKGEGEBEN, Sie arbeiten mit einer anderen session-Daten.
Dies funktioniert gut, sowohl mit der Bündelung von an-und auszuschalten. Die ClientId und ClientInfo auf die Oracle-Sitzung nicht aktualisieren, bis ein Befehl ausgeführt wird.
Könnte Sie überprüfen Sie Ihre if-Anweisung ist korrekt? Wenn _clientID <> "" Dann _oracleConnection.ClientId = _clientID. Sogar, wenn Sie die Verbindung schließen, die clientId wird noch immer gleich bleiben. Sie wissen nicht, wo Sie Ihre Einstellung/erste _clientId wenn Sie übergeben, die in Ihrer Methode.
Die ClientId wird nur zurückgesetzt, auf die Verbindung schließen und wenn Sie schließen dann die gebundenen zurückgesetzt werden.
Verbindungs-pooling hilft die Datenbank-server zu einer Sitzung im Leerlauf-timeout und die Verbindung verwenden, um eine aktive Sitzung. Die idle-logische-Sitzung bleibt geöffnet, und die physikalische Verbindung wird automatisch wiederhergestellt, wenn die nächste Anfrage kommt aus dieser Sitzung. So ist die Verbindung tatsächlich geschlossen ?
Also wäre es gut, um die Session-id DBMS_SESSION.SET_IDENTIFIER
Hoffe, das hilft
Scheint es sehr gefährlich, um mich zu halten, die einen Verweis auf eine Datenbankverbindung in Ihrer Sitzung. Die Idee des connection-pool ist, dass eine Anfrage leiht sich eine Verbindung für die Dauer der Anforderung. Wenn die Anforderung abgeschlossen ist, wird die Verbindung geht zurück zum pool. Die Verbindung wird dann wiederverwendet werden für mehr Anfragen von verschiedenen Benutzern.
Ich vermute, dass alle möglichen schlimmen Dinge passieren, wenn Sie speichern einer Verbindung in Ihre Sitzung. Sie haben wahrscheinlich die Verbindung verwenden, während es gleichzeitig von einer anderen Anforderung. Oder Sie könnten eine geschlossene Verbindung, weil der connectin-pool zu entscheiden hat, um es zu schließen.
Furthmore, den LOGON-trigger ist wahrscheinlich nur ausgeführt, wenn die Datenbank-Verbindung wird zum ersten mal erstellt, aber nicht wieder ausgeführt, wenn die Verbindung wiederverwendet wird, der für einen anderen Antrag oder einem anderen Benutzer.
Ihr problem zu lösen, Holen Sie sich eine Datenbank-Verbindung am Anfang jedes Requests und explizit gesetzt, wird die Client-ID (und/oder ausführen von code durch ausführen des LOGON-trigger). Dann verwenden Sie diese Verbindung für die Dauer der Anforderung. Aber nicht speichern Sie es irgendwo, nachdem die Anfrage beendet ist.
So, die Verbindung wird immer korrekt initialisiert mit dem aktuellen Kontext des Benutzers. Und man sich an die Regeln der connection pool.
Wenn das Verbindungspooling aktiviert ist, was gut und natürlich ist der Weg zu gehen in einer ASP.NET Szenario (und in den meisten Fällen in der Tat), sollten Sie nicht store jedem db-Verbindung. Sie müssen öffnen und schließen von verbindungen, wenn Sie es brauchen.
Hier ist ein link zu SQL Server, aber es ist das gleiche wie bei Oracle, erklärt: SqlConnection-Klasse
So, dass der code müssen Sie beim aufrufen von Oracle sollte so etwas wie dieses, überall in Ihrer app, whenyou müssen es:
Die Sache ist die: Sie können Verbindungs-pooling aktiviert mit bestimmten Benutzer-Informationen in der Verbindungszeichenfolge. Also ich schlage vor, Sie setzen Ihre auditing-code ohne Verwendung der Verbindungszeichenfolge.