Implémentation d'une couche d'accès aux données en VB.NETDate 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
Public Property ColumnName() As String
Get
Return _columnName
End Get
Set(ByVal Value As String)
_columnName = Value
End Set
End Property
Public Property ColumnType() As SqlDbType
Get
Return _columnType
End Get
Set(ByVal Value As SqlDbType)
_columnType = Value
End Set
End Property
Public Property ColumnLength() As Integer
Get
Return _columnLength
End Get
Set(ByVal Value As Integer)
_columnLength = Value
End Set
End Property
Public Property ColumnValue() As Object
Get
Return _columnValue
End Get
Set(ByVal Value As Object)
_columnValue = Value
End Set
End Property
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
Public Property SqlCommand() As SqlCommand
Get
Return _command
End Get
Set(ByVal Value As SqlCommand)
_command = Value
End Set
End Property
Public Property SqlConnection() As SqlConnection
Get
Return _conn
End Get
Set(ByVal Value As SqlConnection)
_conn = Value
End Set
End Property
Public Property Transaction() As SqlTransaction
Get
Return _trans
End Get
Set(ByVal Value As SqlTransaction)
_trans = Value
End Set
End Property
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
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)
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
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
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".
mx.SqlConnection.ConnectionString = mx.SqlConnectionString
mx.SqlConnection.Open()
mx.Transaction = mx.SqlConnection.BeginTransaction()
mx.SqlConnection.Close() |
Suite ...
Ce tutoriel est une traduction provenant d'un article du site CodeProject.
Vous pouvez consulter son article original ici.
Un prochain article est prévu, afin d'appronfondir ce sujet et d'utiliser des composants personnalisés.
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.
|