2009-06-16 10 views
0

Selon la documentation MSDN pour la OracleClient.OracleCommand:commande OracleClient - les meilleures pratiques autour de l'utilisation et l'élimination de commande

Public Sub ReadMyData(ByVal connectionString As String) 
    Dim queryString As String = "SELECT EmpNo, DeptNo FROM Scott.Emp" 
    Using connection As New OracleConnection(connectionString) 
     Dim command As New OracleCommand(queryString, connection) 
     connection.Open() 
     Dim reader As OracleDataReader = command.ExecuteReader() 
     Try 
      While reader.Read() 
       Console.WriteLine(reader.GetInt32(0) & ", " _ 
        & reader.GetInt32(1)) 
      End While 
     Finally 
      ' always call Close when done reading. 
      reader.Close() 
     End Try 
    End Using 
End Sub 

OracleCommand n'est pas englobés dans un bloc utilisant.

Question: Devrait-il être? OracleCommand hérite de DbCommand, qui implémente IDisposable.

Je regarde le code qui fait ce qui suit, et nous avons des problèmes avec les curseurs implicites ne se fermés:

 Dim cmd As OracleCommand = createCommand("some sql") 
    ds = GetDataSet(cmd) 
    cmd.Dispose() 
    cmd = Nothing 

GetDataSet ressemble:

Dim da As New OracleDataAdapter() 
    Dim ds As New DataSet() 

    Using conn As OracleConnection = GetOpenConnection() 
    cmd.Connection = conn 
    da.SelectCommand = cmd 
    da.Fill(ds, 0) 
    cmd.Connection = Nothing 
    End Using 
    da.Dispose() 
    da = Nothing 
    Return ds 

Est-ce que ça va ressources de fuite?

Répondre

1

Tout d'abord, je pense que vous devez fermer explicitement vos connexions dans votre code, car selon le fournisseur il y a un peu de travail supplémentaire qui se fait lorsque vous appelez la méthode Close

+0

Mais selon le code MSDN, ce n'est pas nécessaire. Et si j'ai un bloc Using cmd = new OracleCommand(), ai-je besoin de le fermer explicitement? – chris

+0

La suppression d'une commande ne signifie pas que la connexion associée est fermée. Rappelez-vous qu'une connexion peut être utilisée par plusieurs commandes. – Rad

+0

@Conrad C'est faux. L'utilisation de l'instruction est la pratique la plus connue car elle implémente l'interface IDisposable. En outre, en utilisant Close() est un code gonflé comme si l'utilisation est utilisée ou en appelant Dispose(), la méthode Dispose implicitement TOUJOURS appelle la méthode Close(). –

1

Comment allez-vous déterminer que les curseurs implicites sont ouverts et que c'est un problème? La raison pour laquelle je demande est que l'appel de la méthode "Close" ne ferme pas réellement la connexion. Cela permet au pool de savoir qu'il n'est plus utilisé et peut être réaffecté ailleurs. Ceci est fait pour des raisons de performances car l'ouverture physique d'une connexion est coûteuse. La même connexion sera réutilisée plusieurs fois et peut rester ouverte même après avoir appelé "Fermer", donc si vous utilisez des outils Oracle pour scruter les connexions, cela peut vous égarer.

Je ne l'ai jamais vu aucune raison de disposer explicitement l'objet de commande. C'est juste une collection de paramètres et d'autres informations.

Si vous utilisez un bloc à l'aide que vous avez, il n'y a absolument pas besoin d'appeler « Fermer » ou « Éliminer » explicitement dans le code. C'est tout le point du bloc qui utilise. Il vous protège de l'oubli d'appeler Fermer puisque c'est exactement ce qu'il fait pour vous.

+0

alors pas il sera absolument pas s'appelé! sélectionner a.value, s.username, S.sid, s.status, s.schemaname, s.machine, s.logon_time, s.état, s.serial # de v $ sesstat a, v $ statname b, c de $ session où a.statistiC# = b.statistiC# et S.sid = a.sid et b .name = 'curseurs ouverts en cours' et s.type = 'USER' ordre par nom d'utilisateur; Nous avons max. les curseurs sont réglés à 300, mais nous continuons d'obtenir l'erreur ORA-01000. La surveillance montre que 100 curseurs s'ouvrent à chaque requête (c'est une page de résumé, interroge beaucoup de tables) mais ils ne sont jamais fermés, donc mon hypothèse est que nous ne fermons pas ou que nous ne disposons pas de quelque chose. – chris

+0

Appelez-vous GetDataSet dans une boucle serrée? Libérer la connexion au pool est une opération asynchrone et si vous êtes dans une boucle serrée, il faudra probablement saisir une nouvelle connexion pour chaque itération car elle ne les libère pas assez rapidement. Wow, cela ressemble à beaucoup de connexions pour une page. Peut-être un problème de conception là-bas. – DancesWithBamboo

+1

Certainement un problème de conception, mais il a fait surface le problème. La solution consistait à enrouler chaque nouvelle OracleCommand dans une utilisation, et chaque DataReader dans un problème d'utilisation résolu. La documentation MSDN semble être incorrecte. – chris