Developpez.com - Microsoft DotNET
X

Choisissez d'abord la catégorieensuite la rubrique :


Implémentation d'une couche d'accès aux données en VB.NET

Date de publication : 20/12/2005

Par Settas Antonis
 Xavier VLIEGHE (Traducteur) (autres articles)
 

Cet article a pour but de vous proposer une solution afin de gérer vous-même une couche d'accès à vos données, développée en VB.NET.


Remerciements
Introduction
Ma solution
La Classe Field
La Classe FieldsCollection
La Classe AccessingData
Mise en pratique
Suite ...


Remerciements

L'auteur de cet article est Settas Antonis, je tiens à le remercier chaleureusement pour m'avoir autorisé à traduire son article.


Introduction

Si vous n'êtes pas à l'aise avec les accès aux données via ADO.Net, je vous conseille de vous reporter aux articles/cours suivants :
ADO.NET : Connection, Command et DataReader avec VB.NET
Cours complet sur ADO.NET (130 pages)

Nous entendons fréquement parler d'application n-tiers, de couches, etc. Le but de cet article n'est pas de discuter des divers avantages qu'une telle solution offre, car la plupart des développeurs en sont déjà conscients, mais bien de vous proposer une solution. Depuis mes débuts en .NET, j'ai toujours eu en tête l'idée que je pourrais moi-même développer moi-même une couche d'accès aux données (Data Access Layer, ou DAL), de telle manière que je n'ai plus à m'en préoccuper, afin de me concentrer sur le développement des procédures stockées et de la couche me permettant de piloter mon DAL.


Ma solution

La première partie de ma solution vous est proposée dans cet article. J'ai commencé par développer les parties de base de la couche qui permettent de récupérer des enregistrements et des datasets, de faire des mises à jour ou de supprimer des enregistrements. Cette couche d'accès aux données se compose de 3 classes : Field, FieldsCollection, et AccessingData.


La Classe Field

La classe Field sert simplement à modéliser un champ d'une table. Nous verrons ensuite comment l'utiliser pour la gestion d'un ensemble de champs via une collection dédiée, et pour l'ajout de ceux-ci dans une requête. 4 champs sont gérés : ColumnName, ColumnType, ColumnLength, and ColumnValue. Voici le code de cette classe :

Public Class Field
    Private _columnName As String = ""
    Private _columnType As SqlDbType = SqlDbType.VarChar
    Private _columnLength As Integer = 0
    Private _columnValue As Object
    
    'ColumnName
    Public Property ColumnName() As String
        Get
            Return _columnName
        End Get
        
        Set(ByVal Value As String)
            _columnName = Value
        End Set
    End Property

    'ColumnType
    Public Property ColumnType() As SqlDbType
        Get
            Return _columnType
        End Get
        
        Set(ByVal Value As SqlDbType)
            _columnType = Value
        End Set
    End Property
    
    'ColumnLength
    Public Property ColumnLength() As Integer
        Get
            Return _columnLength
        End Get
        
        Set(ByVal Value As Integer)
            _columnLength = Value
        End Set
    End Property

    'ColumnValue
    Public Property ColumnValue() As Object
        Get
            Return _columnValue
        End Get
        
        Set(ByVal Value As Object)
            _columnValue = Value
        End Set
    End Property

    'Initialisation
    Public Sub New(ByVal colName As String, ByVal colType As SqlDbType, _
                   ByVal colValue As Object, ByVal colLength As Integer)
        Me.ColumnName = colName
        Me.ColumnType = colType
        Me.ColumnLength = colLength
        Me.ColumnValue = colValue
    End Sub
End Class

La Classe FieldsCollection

Cette classe sert uniquement à gérer une collection de champs, ç-à-d ici d'objets de la classe Field. Elle est dérivée de la classe System.Collections.CollectionBase. Voici le code de cette classe :

Public Class FieldsCollection

    Inherits System.Collections.CollectionBase

    Public Sub Add(ByVal objItemToAdd As Field)
        Me.List.Add(objItemToAdd)
    End Sub

    Public ReadOnly Property Item(ByVal iIndex As Integer) As Field
        Get
            Return Me.List(iIndex)
        End Get
    End Property
End Class

La Classe AccessingData

Voici le coeur de notre DAC : cette classe gère 4 propriétés :
- la connexion ,
- la chaîne de connexion (renseignée à partir du fichier App.config),
- la commande (SqlCommand),
- la transaction ,
Ainsi que les fonctions pour :
- lire le contenu d'une table via un DataSet (table entière - Get_Dataset),
- lire un seul enregistrement à partir de sa clé (Get_record),
- supprimer un enregistrement (Delete_record),
- modifier un enregistrement (Update_record).

Il est possible d'inclure les appels de ces fonctions au sein d'une transaction. Si aucune transaction n'est en cours, c'est le DAC qui se chargera lui-même de l'ouverture ainsi que de la fermeture de la connexion.

Voici le code de cette classe :

Imports System.Data.SqlClient

Public Class AccessingData
    Private _conn As New SqlConnection
    Private _trans As SqlTransaction
    Private _connectionstring As String = _
      System.Configuration.ConfigurationSettings.AppSettings("SQLconn")
    Private _command As New SqlCommand
    
    'Property SqlCommand
    Public Property SqlCommand() As SqlCommand
        Get
            Return _command
        End Get
        Set(ByVal Value As SqlCommand)
            _command = Value
        End Set
    End Property
    
    'Property SqlConnection
    Public Property SqlConnection() As SqlConnection
        Get
            Return _conn
        End Get
        Set(ByVal Value As SqlConnection)
            _conn = Value
        End Set
    End Property
    
    'Property Transaction
    Public Property Transaction() As SqlTransaction
        Get
            Return _trans
        End Get
        Set(ByVal Value As SqlTransaction)
            _trans = Value
        End Set
    End Property
    
    'Property SqlConnectionString
    Public Property SqlConnectionString() As String
        Get
            Return _connectionstring
        End Get
        Set(ByVal Value As String)
            _connectionstring = Value
        End Set
    End Property
    
    
    Public Function Get_Dataset(ByVal storedprocedurename As String, _
                                ByVal datatable As String) As DataSet
        Dim sqlDataAdapter As New SqlDataAdapter
        Try
            sqlDataAdapter.SelectCommand = New SqlCommand
            If _conn.ConnectionString = "" Then
                _conn.ConnectionString = _connectionstring
            End If
            sqlDataAdapter.SelectCommand.Connection = _conn
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If
            sqlDataAdapter.SelectCommand.CommandText = storedprocedurename
            sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure
            If Not IsNothing(_trans) Then
                sqlDataAdapter.SelectCommand.Transaction = _trans
            End If

            Dim myDataSet As DataSet = New DataSet
            sqlDataAdapter.Fill(myDataSet, datatable)
            Return myDataSet
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If

        End Try
    End Function
    
    Public Function Get_record_byID(ByVal myField As Field, _
                                    ByVal storedprocedurename As String, _
                                    ByVal datatable As String) As DataSet
        Dim sqlDataAdapter As New SqlDataAdapter
        Try
            sqlDataAdapter.SelectCommand = New SqlCommand
            If _conn.ConnectionString = "" Then
                _conn.ConnectionString = _connectionstring
            End If

            sqlDataAdapter.SelectCommand.Connection = _conn
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If

            sqlDataAdapter.SelectCommand.CommandText = storedprocedurename
            sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure
            If Not IsNothing(_trans) Then
                sqlDataAdapter.SelectCommand.Transaction = _trans
            End If
            'Parameters
            Dim myparam As SqlParameter
            myparam = New SqlParameter("@" & myField.ColumnName, _
                                       myField.ColumnType, myField.ColumnLength)
            myparam.Value = myField.ColumnValue
            myparam.Direction = ParameterDirection.Input
            sqlDataAdapter.SelectCommand.Parameters.Add(myparam)

            'sqlDataAdapter.SelectCommand.ExecuteNonQuery()
            Dim myDataSet As DataSet = New DataSet
            sqlDataAdapter.Fill(myDataSet, datatable)
            Return myDataSet
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Function
    
    Public Sub Delete_record(ByVal myField As Field, _
                             ByVal storedprocedure As String)

        Dim mycommand As New SqlCommand
        mycommand.CommandType = CommandType.StoredProcedure
        Try
            mycommand.Connection = _conn
            If _conn.ConnectionString = "" Then
                _conn.ConnectionString = _connectionstring
            End If
            If Not IsNothing(_trans) Then
                mycommand.Transaction = _trans
            End If
            mycommand.CommandText = storedprocedure

            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If

            'Parameters
            Dim myparam As SqlParameter
            myparam = New SqlParameter("@" & myField.ColumnName, _
                                       myField.ColumnType, myField.ColumnLength)
            myparam.Value = myField.ColumnValue
            myparam.Direction = ParameterDirection.Input
            mycommand.Parameters.Add(myparam)

            mycommand.ExecuteNonQuery()
        Catch ex As Exception
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Sub
    
    Public Sub Update_Record(ByVal storedprocedure As String, _
                             ByVal myFieldsCollection As FieldsCollection)
        Try
            Dim mycommand As New SqlCommand
            mycommand.CommandType = CommandType.StoredProcedure
            mycommand.CommandText = storedprocedure
            mycommand.Connection = _conn
            If _conn.ConnectionString = "" Then
                _conn.ConnectionString = _connectionstring
            End If
            If Not IsNothing(_trans) Then
                mycommand.Transaction = _trans
            End If
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If
            'Parameters
            Dim myparam As SqlParameter
            For i As Integer = 0 To myFieldsCollection.Count - 1
                Dim obj As Field
                obj = myFieldsCollection.Item(i)

                myparam = New SqlParameter("@" & obj.ColumnName, _
                                           obj.ColumnType, obj.ColumnLength)
                myparam.Value = obj.ColumnValue

                myparam.Direction = ParameterDirection.Input
                mycommand.Parameters.Add(myparam)
            Next
            mycommand.ExecuteNonQuery()
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Sub
End Class

Afin d'utiliser le code précédent, il suffit de développer les procédures stockées correspondant à nos besoin : lectures d'enregistrement, insertions, etc. Nous allons utiliser la BDD NorthWind de SQL Server pour notre exemple, via la procédure suivante qui permet de mettre à jour la table Region :
CREATE  PROCEDURE DBO.UPDATE_REGION
@REGIONDESCRIPTION VARCHAR (50),
@REGION_ID INT

AS
BEGIN
    UPDATE REGION
       SET REGIONDESCRIPTION = @REGIONDESCRIPTION 
     WHERE REGIONID = @REGION_ID
END
GO

Mise en pratique

Pour que le tout fonctionne, il suffit enfin de référencer notre DLL au niveau de notre projet. Pour la mise à jour de la table région, il suffit alors de passer par le code suivant :
Dim mx As New AccessingData
Try
       Dim myField1 As New Field("REGIONDESCRIPTION", _
                       SqlDbType.NChar, "REGION1", 50)
       Dim myCollection As New FieldsCollection
       myCollection.Add(myField1)
       myField1 = Nothing
       Dim myField2 As New Field("REGION_ID", SqlDbType.Int, 1, 4)
       myCollection.Add(myField2)
       myField2 = Nothing

       mx.Update_Record("UPDATE_REGION", myCollection)
Catch ex As Exception

End Try
Si une transaction était requise, il nous suffirait alors d'insérer le code suivant avant l'instruction "Update_Record".
'With transaction
mx.SqlConnection.ConnectionString = mx.SqlConnectionString
mx.SqlConnection.Open()
mx.Transaction = mx.SqlConnection.BeginTransaction()
'But after that dont forget to close the connection:
mx.SqlConnection.Close()

Suite ...

Ce tutoriel est une traduction provenant d'un article du site en CodeProject.
Vous pouvez consulter son article original en ici.

Un prochain article est prévu, afin d'appronfondir ce sujet et d'utiliser des composants personnalisés.



Valid XHTML 1.1!Valid CSS!

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.
Responsable bénévole de la rubrique Microsoft DotNET : Hinault Romaric -