Friday, October 19, 2007

Implementing Data Transfer Objects

When you separate your business layer from data access layer in two different assembly, you come across a situation as which data transfer method will be best for me. In this example, I went through various data transfer object currently available in .NET such as XML, DataSet, DataTable, ArrayList and Custom Data Transfer Object. Each option has its pros and cons, so depending on project one should choose as what best fits the need. In the following code I have tried to use all the four possibilities.

I will be consuming the data which was returned by Data Access Layer in the form of XML, Dataset, DataTable, ArrayList and Custom (Data Transfer) Objects to populating my Business Object, which will be finally consumed by a User Interface and most likely a web page. 

In this example, I will use only one class, which will perform the CRUD operation on Customer Object by invoking method of Data Access Layer. Since I have added methods in data access layer to return Customer(s) data in form on XML, Dataset, DataTable, ArrayList and Custom (Data Transfer) Object. No matter in which form data is returned from data access layer, the business object will read that object and consume the data to make it ready for business object caller.

This Business Object will refer the assembly I previously created Vishwa.Example.Data in my earlier post Data Transfer Objects (DTO) - Data Access Layer .

Following are the steps
          Created a Class Library Project in Visual Studio 2005 using language VB.NET
 
           Project Name: Vishwa.Example.Business
          Class Name: CustomerBiz.vb
 
 
CustomerBiz.vb
' <summary>
'   Customer Business Object
' </summary>
' <remarks>
'   Design Pattern: Domain Model and Identity Field
' </remarks>
Option Explicit On
Option Strict On
Imports Vishwa.Example.Data
Imports Vishwa.Example.Data.DataAccess
 
Namespace Example.Business
 
    <Serializable()> _
    Public Class CustomerBiz
        Private _custID As Integer = 0
        Private _custName As String = String.Empty
        Private _custDOB As DateTime = DateTime.MinValue
        Private _custAddress As String = String.Empty
        Private _dateCreated As DateTime = DateTime.Now
        Private _dateModified As DateTime = DateTime.Now
 
#Region "Constructor"
        Public Sub New()
 
        End Sub
#End Region
 
#Region "Properties"
 
        Public Property CustID() As Integer
            Get
                Return _custID
            End Get
 
            Set(ByVal value As Int32)
                _custID = value
            End Set
        End Property
 
        Public Property CustName() As String
            Get
                Return _custName
            End Get
            Set(ByVal value As String)
                _custName = value
            End Set
        End Property
 
        Public Property CustDOB() As DateTime
            Get
                Return _custDOB
            End Get
            Set(ByVal value As DateTime)
                _custDOB = value
            End Set
        End Property
 
        Public Property CustAddress() As String
            Get
                Return _custAddress
            End Get
            Set(ByVal value As String)
                _custAddress = value
            End Set
        End Property
 
        Public Property DateCreated() As DateTime
            Get
                Return _dateCreated
            End Get
            Set(ByVal value As DateTime)
                _dateCreated = value
            End Set
        End Property
 
        Public Property DateModified() As DateTime
            Get
                Return _dateModified
            End Get
            Set(ByVal value As DateTime)
                _dateModified = value
            End Set
        End Property
 
        ' A Simple example of Business Logic to Get Customer Age
        ' Such logics are created in Business Logic/Object Layer    
 
        Public ReadOnly Property CustAge() As Long
            Get
                If _custDOB > DateTime.MinValue Then
                    Return DateDiff(DateInterval.Year, _custDOB, Now())
                Else
                    Return 0
                End If
            End Get
        End Property
#End Region
 
#Region "Customer Methods"
 
        Public Function AddBlankCustomer() As Integer
            Return DataProvider.InsertCustomer("unknown", DateTime.Now, "Unknown")
        End Function
 
        Public Overloads Function AddCustomer(ByVal custInfo As CustomerBiz) As Integer
            Return DataProvider.InsertCustomer(custInfo.CustName, custInfo.CustDOB, "Unknown")
        End Function
 
        Public Overloads Function AddCustomer(ByVal custName As String, ByVal custDOB As DateTime, _
                                              ByVal custAddress As String) As Integer
            Return DataProvider.InsertCustomer(custName, custDOB, custAddress)
        End Function
 
        Public Overloads Function UpdateCustomer(ByVal custInfo As CustomerBiz) As Boolean
            Return DataProvider.UpdateCustomer(custInfo.CustID, custInfo.CustName, custInfo.CustDOB, custInfo.CustAddress)
        End Function
 
        Public Overloads Function UpdateCustomer(ByVal custID As Integer, ByVal custName As String, _
             ByVal custDOB As DateTime, ByVal custAddress As String) As Boolean
            Return DataProvider.UpdateCustomer(custID, custName, custDOB, custAddress)
        End Function
 
        Public Overloads Function DeleteCustomer(ByVal custID As Integer) As Boolean
            Return DataProvider.DeleteCustomer(custID)
        End Function
 
        Public Overloads Function DeleteCustomer(ByVal custInfo As CustomerBiz) As Boolean
            Return DataProvider.DeleteCustomer(custInfo.CustID)
        End Function
 
#Region "Get Customers From Custom Data Transfer Object"
        Public Function GetCustomer(ByVal custID As Integer) As CustomerBiz
            Dim custDTORec As New CustomerDTO
            Dim custBIZRec As New CustomerBiz
            custDTORec = DataProvider.GetCustomer(custID)
            If Not custDTORec Is Nothing Then
                custBIZRec = GetCustomerRow(custDTORec)
            End If
            Return custBIZRec
        End Function
 
        Public Function GetCustomers() As List(Of CustomerBiz)
            Dim custBIZRecs As New List(Of CustomerBiz)
            Dim custDTORecs As New List(Of CustomerDTO)
            custDTORecs = DataProvider.GetCustomers
 
            For Each custDTORec As CustomerDTO In custDTORecs
                Dim custBIZRec As CustomerBiz = GetCustomerRow(custDTORec)
                custBIZRecs.Add(custBIZRec)
            Next
            Return custBIZRecs
        End Function
 
#End Region
 
#Region "Consuming Get Methods of Other Data Trasfer Objects"
 
#Region "Get Customers From DataSet Object"
        Public Function GetCustomerFromDataSet(ByVal custID As Integer) As CustomerBiz
            Dim custDataSet As New DataSet("Customer")
            Dim custBIZRec As New CustomerBiz
            custDataSet = DataProvider.GetCustomerAsDataSet(custID)
            If Not custDataSet Is Nothing AndAlso custDataSet.Tables.Count = 1 Then
                custBIZRec = GetCustomerRow(custDataSet.Tables(0).Rows(0))
            End If
            Return custBIZRec
        End Function
 
        Public Function GetCustomersFromDataSet() As List(Of CustomerBiz)
            Dim custDataSet As New DataSet("Customers")
            Dim custBIZRecs As New List(Of CustomerBiz)
            custDataSet = DataProvider.GetCustomersAsDataSet()
 
            If Not custDataSet Is Nothing AndAlso custDataSet.Tables.Count = 1 Then
                For Each row As DataRow In custDataSet.Tables(0).Rows
                    Dim custBIZRec As CustomerBiz = GetCustomerRow(row)
                    custBIZRecs.Add(custBIZRec)
                Next
            End If
            Return custBIZRecs
        End Function
 
#End Region
 
#Region "Get Customers From DataTable Object"
        Public Function GetCustomerFromDataTable(ByVal custID As Integer) As CustomerBiz
            Dim custDataTable As New DataTable("Customer")
            Dim custBIZRec As New CustomerBiz
            custDataTable = DataProvider.GetCustomerAsDataTable(custID)
 
            If Not custDataTable Is Nothing AndAlso custDataTable.Rows.Count > 0 Then
                custBIZRec = GetCustomerRow(custDataTable.Rows(0))
            End If
            Return custBIZRec
        End Function
 
        Public Function GetCustomersFromDataTable() As List(Of CustomerBiz)
            Dim custDataTable As New DataTable("Customers")
            Dim custBIZRecs As New List(Of CustomerBiz)
            custDataTable = DataProvider.GetCustomersAsDataTable()
 
            If Not custDataTable Is Nothing AndAlso custDataTable.Rows.Count > 0 Then
                For Each row As DataRow In custDataTable.Rows
                    Dim custBIZRec As CustomerBiz = GetCustomerRow(row)
                    custBIZRecs.Add(custBIZRec)
                Next
            End If
            Return custBIZRecs
        End Function
#End Region
 
#Region "Get Customers From XML"
        Public Function GetCustomerFromXML(ByVal custID As Integer) As CustomerBiz
            Dim custBIZRecs As New List(Of CustomerBiz)
            Dim custBIZRec As New CustomerBiz
 
            Dim custXMLString As String = DataProvider.GetCustomersAsXMLString()
            If custXMLString.Length > 0 Then
                custBIZRecs = ReadCustomerXML(custXMLString)
                If Not custBIZRecs.Count > 0 Then custBIZRec = custBIZRecs(0)
            End If
 
            Return custBIZRec
        End Function
 
        Public Function GetCustomersFromXML() As List(Of CustomerBiz)
            Dim custBIZRecs As New List(Of CustomerBiz)
           Dim custXMLString As String = DataProvider.GetCustomersAsXMLString()
            If custXMLString.Length > 0 Then
                custBIZRecs = ReadCustomerXML(custXMLString)
            End If
            Return custBIZRecs
        End Function
 
#End Region
 
#Region "Get Customers From ArrayList Object"
        Public Function GetCustomerFromArrayList(ByVal custID As Integer) As CustomerBiz
            Dim custBIZRec As New CustomerBiz
            Dim custArrList As New ArrayList()
            custArrList = DataProvider.GetCustomerAsArrayList(custID)
 
            If Not custArrList Is Nothing AndAlso custArrList.Count > 0 Then
                custBIZRec = GetCustomerRow(custArrList)
            End If
            Return custBIZRec
       End Function
 
        Public Function GetCustomersFromArrayList() As List(Of CustomerBiz)
            Dim custBIZRecs As New List(Of CustomerBiz)
            Dim custArrList As New ArrayList()
            custArrList = DataProvider.GetCustomersAsArrayList()
 
            If Not custArrList Is Nothing AndAlso custArrList.Count > 0 Then
                For Each row As ArrayList In custArrList
                    Dim custBIZRec As CustomerBiz = GetCustomerRow(row)
                    custBIZRecs.Add(custBIZRec)
                Next
            End If
            Return custBIZRecs
        End Function
#End Region
 
#End Region
 
#Region "Common Methods to Transfer data from DTO to Business Object"
        Private Function GetCustomerRow(ByVal row As DataRow) As CustomerBiz
            Dim custBIZRec As New CustomerBiz
            If Not IsDBNull(row.Item("Cust_ID")) Then custBIZRec.CustID = CInt(row.Item("Cust_ID"))
            If Not IsDBNull(row.Item("Cust_DOB")) Then custBIZRec.CustDOB = CDate(row.Item("Cust_DOB"))
            If Not IsDBNull(row.Item("Cust_Name")) Then custBIZRec.CustName = row.Item("Cust_Name").ToString
            If Not IsDBNull(row.Item("Cust_Address")) Then custBIZRec.CustAddress = row.Item("Cust_Address").ToString
            If Not IsDBNull(row.Item("Date_Created")) Then custBIZRec.DateCreated = CDate(row.Item("Date_Created"))
            If Not IsDBNull(row.Item("Date_Modified")) Then custBIZRec.DateModified = CDate(row.Item("Date_Modified"))
            Return custBIZRec
        End Function
 
        Private Function GetCustomerRow(ByVal custDTORec As CustomerDTO) As CustomerBiz
            Dim custBIZRec As New CustomerBiz
            custBIZRec.CustID = custDTORec.CustID
            custBIZRec.CustName = custDTORec.CustName
            custBIZRec.CustDOB = custDTORec.CustDOB
            custBIZRec.CustAddress = custDTORec.CustAddress
            custBIZRec.DateCreated = custDTORec.DateCreated
            custBIZRec.DateModified = custDTORec.DateModified
            Return custBIZRec
        End Function
 
        Private Function GetCustomerRow(ByVal custArrList As ArrayList) As CustomerBiz
            Dim custBIZRec As New CustomerBiz
            If IsNumeric(custArrList.Item(0)) Then custBIZRec.CustID = CInt(custArrList.Item(0))
            If Not custArrList.Item(1) Is Nothing Then custBIZRec.CustName = custArrList.Item(1).ToString
            If IsDate(custArrList.Item(2)) Then custBIZRec.CustDOB = CDate(custArrList.Item(2))
            If Not custArrList.Item(3) Is Nothing Then custBIZRec.CustAddress = custArrList.Item(3).ToString
            If IsDate(custArrList.Item(4)) Then custBIZRec.DateCreated = CDate(custArrList.Item(4))
            If IsDate(custArrList.Item(5)) Then custBIZRec.DateModified = CDate(custArrList.Item(5))
            Return custBIZRec
        End Function
 
        Private Function ReadCustomerXML(ByVal xmlDocString As String) As List(Of CustomerBiz)
            Dim customers As New List(Of CustomerBiz)
            Dim status As Integer = 0
            Dim statusDescription As String = String.Empty
            Dim uniEncoding As New System.Text.ASCIIEncoding()
            Dim stringBytes As Byte() = uniEncoding.GetBytes(xmlDocString)
            Dim xmlDocSteam As New System.IO.MemoryStream(stringBytes, 0, stringBytes.Length)
 
            Using xmlDocReader As System.Xml.XmlReader = System.Xml.XmlReader.Create(xmlDocSteam)
                xmlDocReader.Read()
                xmlDocReader.MoveToContent()
 
                While xmlDocReader.Read()
                    If xmlDocReader.NodeType = System.Xml.XmlNodeType.Element And xmlDocReader.Name = "Customer" Then
                        Dim custRec As New CustomerBiz
                        While (xmlDocReader.Read() And xmlDocReader.Name <> "Customer")
                            If xmlDocReader.Name.Length > 0 Then
                                If xmlDocReader.Name = "Cust_ID" Then custRec.CustID = xmlDocReader.ReadElementContentAsInt("Cust_ID", "")
                                If xmlDocReader.Name = "Cust_Name" Then custRec.CustName = xmlDocReader.ReadElementContentAsString("Cust_Name", "")
                                If xmlDocReader.Name = "Cust_DOB" Then custRec.CustDOB = xmlDocReader.ReadElementContentAsDateTime("Cust_DOB", "")
                                If xmlDocReader.Name = "Cust_Address" Then custRec.CustAddress = xmlDocReader.ReadElementContentAsString("Cust_Address", "")
                                If xmlDocReader.Name = "Date_Created" Then custRec.DateCreated = xmlDocReader.ReadElementContentAsDateTime("Date_Created", "")
                                If xmlDocReader.Name = "Date_Modified" Then custRec.DateModified = xmlDocReader.ReadElementContentAsDateTime("Date_Modified", "")
                            End If
                        End While
                        customers.Add(custRec)
                    End If
                End While
            End Using
            xmlDocSteam.Close()
            Return customers
        End Function
 
#End Region
 
#End Region
 
    End Class
End Namespace
Compiled Assembly Name: Vishwa.Example.Business.dll
Now you can use the reference of the above assembly for customer object in your ASP.NET Web Page and test the functionality.

No comments: