2009-02-27 3 views
2

Je connais bien la façon dont VB6 ADO traite les requêtes SQL et parcourt les résultats du jeu d'enregistrements.vb.net parcourir les résultats de la requête

Cependant, quelle est la bonne façon d'interroger un serveur, parcourir les résultats et éliminer ma requête dans VB.Net? Toutes les manières que j'ai employées semblent être instables et planter aléatoirement.

J'utilise le code suivant:

Public Function GetSQLTable(ByVal strSQL As String) As DataTable 
    Dim table As New DataTable 
    Dim adapt As SqlDataAdapter 

    Try 
     adapt = New SqlDataAdapter(strSQL, gconIntegration) 
     adapt.Fill(table) 
    Catch ex As Exception 
     LogError("GetSQLTable: " & ex.ToString(), "SQL: " & strSQL) 
    End Try 

    Return table 
End Function 

Et en utilisant comme ceci:

Dim dt As DataTable 
Dim lngRow As Long 
Dim current As DataRow 
Dim lngContact As long 

Try 
     dt = GetSQLTable(strSQL) 
     For lngRow = 0 To dt.Rows.Count - 1 
      current = dt.Rows.Item(lngRow) 
      lngContact = current.Item("indvid") 
      DoSomething(lngContact) 
     Next 
Catch ex As Exception 
    LogError("FindContact: " & ex.ToString(), "SQL: " & strSQL) 
    lngContact = -1  
Finally 
    current = nothing 
    dt = nothing 

Répondre

7

Je soupçonne que le problème a à voir avec la façon dont vous gérez votre connexion gconIntegration. Vous essayez trop de continuer à utiliser la même connexion. Il serait utile de voir où il vit.

Mieux vaut obtenir de "nouvelles" connexions de la piscine et laissez-vous inquiéter .Net à ce sujet pour vous.

En outre, votre code générique "GetSQLTable" manque une partie importante: il ne tient pas compte de la définition des paramètres, ce qui me dit que vous les construisez directement dans vos chaînes de requête. C'est une recette pour un désastre: cela conduira à des trous de sécurité d'injection Sql.

Encore une chose: ne définissez pas d'objets sur Nothing dans .Net. Disposez-les si nécessaire ou laissez-les tomber hors de portée par leurs propres moyens.

Voilà ma méthode normale pour tirer en arrière un datatable d'un datatable:

Function GetSomeData(ByVal Table2ID As Integer) 
    Dim result As New DataTable 

    Dim sql As String = "SELECT Column1,Column2 FROM [Table1] WHERE Table2ID= @Table2ID" 

    Using cn As New SqlConnection(GetConnectionString()), _ 
    Using cmd As New SqlCommand(sql, cn) 

     cmd.Parameters.Add("@Table2ID", SqlDbType.Int).Value = Table2ID 

     Using rdr As SqlDataReader = cmd.ExecuteReader() 
      result.Load(rdr) 
     End Using 
    End Using 
    return result 
End Function 

Quelques notes sur ce code:

  • La déclaration Using garantit que l'objet associé est disposé au niveau correspondant End Using.
  • Les paramètres de la requête sont conservés fortement typés, et jamais substitué directement dans la chaîne de requête, même lorsqu'ils sont transmis au serveur. Sql Data et Sql Code ne se mélangent jamais.
  • Vous avez besoin d'une fonction distincte pour chaque requête que vous devez envoyer. C'est vraiment une bonne chose, car cela conduit à la construction d'une interface fortement typée pour votre base de données. Idéalement, toutes ces fonctions sont dans la même classe et la fonction GetConnectionString est privée à cette classe. Aucun accès à la base de données n'a lieu en dehors de cette couche de données.
+0

gconIntegration est une connexion globale. Donc, vous dites qu'une seule connexion pour toutes mes lectures et écritures n'est pas optimale? –

+0

Injection SQL n'est pas vraiment un problème quand ce n'est pas une application web (c'est en fait un exe compilé) –

+0

Correct- ce design vous oblige à faire tout votre travail de base de données en série. Ceci est particulièrement mauvais pour un site Web, où toutes les demandes sont dans la même application. Les connexions de pools .Net pour vous en arrière-plan, il n'est donc pas nécessaire de rester connecté globalement. –

Questions connexes