The Only Data Access Layer You'll Ever Need?, Page 4
Putting It All Together
With the basic code described so far, you need to do significantly less work to flesh out the rest of any DAL. You will probably want a data access class for groups of business objects. These classes will contain code to initiate read and write calls and the read and write handlers themselves.
Listing 6 shows a basic CustomerAccess class that kicks off reads (and writes, not shown), and contains the read (and write) handlers. It demonstrates how to implement a read event handler and it also demonstrates how to invoke the reflection-read.
Listing 6: The CustomerAccess Class
Imports System
Imports System.Data
Imports System.Diagnostics
Imports System.Configuration
Imports System.Collections.Generic
Imports System.Web
Imports MYVB.BusinessObjects
Public Class CustomerAccess
Public Shared Function GetCustomers() As List(Of Customer)
'Return DataAccess.Read(Of List(Of Customer))("GetCustomers",
'AddressOf OnReadCustomers)
Return DataAccess.Read(Of List(Of Customer))("GetCustomers", _
AddressOf DataAccess.OnReadAnyList(Of Customer))
End Function
Public Shared Function OnReadCustomers(ByVal reader As IDataReader) _
As List(Of Customer)
If (reader Is Nothing) Then Return New List(Of Customer)()
Dim customers As List(Of Customer) = New List(Of Customer)()
While (reader.Read())
customers.Add(OnReadCustomer(reader))
End While
Return customers
End Function
Private Shared Function OnReadCustomer(ByVal reader _
As IDataReader) As Customer
Debug.Assert(reader Is Nothing = False)
Dim customerID As String = ""
Dim companyName As String = ""
Dim contactName As String = ""
Dim contactTitle As String = ""
Dim address As String = ""
Dim city As String = ""
Dim region As String = ""
Dim postalCode As String = ""
Dim country As String = ""
Dim phone As String = ""
Dim fax As String = ""
customerID = DataAccess.SafeRead(Of String)(customerID, reader, _
"CustomerID")
companyName = DataAccess.SafeRead(Of String)(companyName, _
reader, "CompanyName")
contactName = DataAccess.SafeRead(Of String)(contactName, _
reader, "ContactName")
contactTitle = DataAccess.SafeRead(Of String)(contactTitle, _
reader, "ContactTitle")
address = DataAccess.SafeRead(Of String)(address, reader, "Address")
city = DataAccess.SafeRead(Of String)(city, reader, "City")
region = DataAccess.SafeRead(Of String)(region, reader, "Region")
postalCode = DataAccess.SafeRead(Of String)(postalCode, reader, _
"PostalCode")
country = DataAccess.SafeRead(Of String)(country, reader, "Country")
phone = DataAccess.SafeRead(Of String)(phone, reader, "Phone")
fax = DataAccess.SafeRead(Of String)(fax, reader, "Fax")
Return New Customer(customerID, companyName, contactName, _
contactTitle, address, city, region, postalCode, country, _
phone, fax)
End Function
End Class
You can use this exemplar to implement all of your custom data access classes.
Tip: Although you do need to write some additional data access code for your custom objects, you could easily write a CodeDOM code generator or use a tool such as CodeRush to really speed up this part of the data access development.
Listing 7 shows the custom Customer object populated by the CustomerAccess class. If you need a collection of objects, use List<T>, the generic collection class.
Listing 7: An Example of a Basic Custom Business Object
<Serializable()> _
Public Class Customer
Private FCustomerID As String
<ColumnName("CustomerID")> _
Public Property CustomerID() As String
Get
Return FCustomerID
End Get
Set(ByVal value As String)
FCustomerID = value
End Set
End Property
Private FCompanyName As String
Public Property CompanyName() As String
Get
Return FCompanyName
End Get
Set(ByVal value As String)
FCompanyName = value
End Set
End Property
Private FContactName As String
Public Property ContactName() As String
Get
Return FContactName
End Get
Set(ByVal value As String)
FContactName = value
End Set
End Property
Private FContactTitle As String
Public Property ContactTitle() As String
Get
Return FContactTitle
End Get
Set(ByVal value As String)
FContactTitle = value
End Set
End Property
Private FAddress As String
Public Property Address() As String
Get
Return FAddress
End Get
Set(ByVal value As String)
FAddress = value
End Set
End Property
Private FCity As String
Public Property City() As String
Get
Return FCity
End Get
Set(ByVal value As String)
FCity = value
End Set
End Property
Private FRegion As String
Public Property Region() As String
Get
Return FRegion
End Get
Set(ByVal value As String)
FRegion = value
End Set
End Property
Private FPostalCode As String
Public Property PostalCode() As String
Get
Return FPostalCode
End Get
Set(ByVal value As String)
FPostalCode = value
End Set
End Property
Private FCountry As String
Public Property Country() As String
Get
Return FCountry
End Get
Set(ByVal value As String)
FCountry = value
End Set
End Property
Private FPhone As String
Public Property Phone() As String
Get
Return FPhone
End Get
Set(ByVal value As String)
FPhone = value
End Set
End Property
Private FFax As String
Public Property Fax() As String
Get
Return FFax
End Get
Set(ByVal value As String)
FFax = value
End Set
End Property
Public Sub New()
End Sub
Public Sub New(ByVal customerID As String, ByVal companyName _
As String, _
ByVal contactName As String, ByVal contactTitle As String, _
ByVal address As String, _
ByVal city As String, ByVal region As String, _
ByVal postalCode As String, _
ByVal country As String, ByVal phone As String, ByVal fax As String)
Me.FCustomerID = customerID
Me.FCompanyName = companyName
Me.FContactName = contactName
Me.FContactTitle = contactTitle
Me.FAddress = address
Me.FCity = city
Me.FRegion = region
Me.FPostalCode = postalCode
Me.FCountry = country
Me.FPhone = phone
End Sub
End Class
The DAL refers to the business object layer and not the other way around. This means that business objects don't need to carry any database knowledge (or baggage) around with them.
By using generic Lists—List(Of T)—you don't need to write custom collections. Generic lists are enumerable and bindable. That said, I often inherit from the generic List—for example, List(Of Customer)—to add additional behaviors to my custom business object collections.
