Resumé

Generic Adapter (Of T) and integrated CRUD

Cristian Merighi () 0.00

A Generic API to handle, in their whole complexity, CRUD procedures in association with custom Business Logic Entities. A real steady first step along the path toward DynamicMethods and runtime code generation...
This article is obsolete. Some functionalities might not work anymore. Comments are disabled.

I'm pretty proud of what I'm packing together... my Pacem.Data.Adapter<T> promises to make me spake a lot of time in my future applications development. And, at the same time, it will grant much more affordability because of its already tuned features!

The whole thing begun as I started to be unsatisfied about hard-coding every step from Database to GUI - passing through DALC (Data Access Layer Components), DAL (Data Access Layer) and BLL (Business Logic Layer)... one, two, three times! ...enough.

I wanted that the only necessary lines of code to write in my data driven application were related to SQL queries and, of course, custom Graphics User Interface (XHTML or similar).

I started (see this article) by creating abstract classes with basic implementations for easy population.
"..yes, it is quite good but just a minor step in my path to complete CRUDding..."

Then I coupled classes and particular objects I called Adapters (lack of fantasy, I know) which could handle insertion, updating and deleting for single instances of BLL entities (see this other article).
"...yes, better! But the CRUD features are splitted among different objects, that's not good design approach, and - above all - I'm still missing selecting features to get juicy lists of custom Business Layer objects!"

Here it comes my generic Adapter<T> (or Adapter(Of T) if you prefer the VB syntax). It is the only delegate to handle Business Logic Entities, both single instances and generic lists, mapping database fields to specific properties/fields marked using Pacem.Reflection.FieldAttribute attributes (custom attributes of mine).

The logic should be explaned by the following picture:

Class Diagram

My Adapter can be created from an xml file respecting a precise schema. Something like the following:

<?xml version="1.0" encoding="utf-8" ?>
<Adapter SourceTable="tblTest" EntitiesTable="Test" 
DataBaseType="OleDb" 
ConnectionStringName="MyConfigConnectionString"
xmlns="http://www.pacem.it/schemas/pacem/data/adapter">
  <SelectCommands>
    <SelectCommand Name="GetList" RequiresTransaction="false">
      <CommandText>SELECT * FROM tblTest WHERE DateTime > @Date</CommandText>
      <Parameters>
        <Parameter DbType="Date" Name="@Date"/>
      </Parameters>
    </SelectCommand>
  </SelectCommands>
  <InsertCommand CommandType="Text" RequiresTransaction="true">
    INSERT INTO [tblTest]
    ([Description],[DateTime]
    )
    VALUES
    (@Desc
    ,@Date)
  </InsertCommand>
  <UpdateCommand>
    UPDATE [tblTest]
    SET [Description] = @Desc
    ,[DateTime] = @Date
    WHERE ID = @ID
  </UpdateCommand>
  <DeleteCommand>
    DELETE FROM tblTest WHERE ID = @ID
  </DeleteCommand>
  <Columns>
    <ColumnMapper
      SourceColumn="ID"
      EntityColumn="ID"
      UpdateParameter="@ID"
      DeleteParameter="@ID"
      DbType="Int32"  />
    <ColumnMapper
      SourceColumn="strDescription"
      EntityColumn="Description"
      InsertParameter="@Desc"
      UpdateParameter="@Desc"
      DbType="String" />
    <ColumnMapper
      SourceColumn="dteDate"
      EntityColumn="DateTime"
      InsertParameter="@Date"
      UpdateParameter="@Date"
      DbType="Date"/>
  </Columns>
</Adapter>

This is a mere sample adapter, it can be much more complex and it can support custom paging in order to match DataSource WebControls' features!
I'll put now some code about how to exploit an Adapter of mine...

Here's an ObjectDataSource WebControl associated with a GridView
(please note the string format of a generic Type, highlighted, and the related backtick char "`". See msdn reference for that).

<asp:ObjectDataSource EnablePaging="true" DataObjectTypeName="TestBLL,__Code" 
InsertMethod="Save" UpdateMethod="Save" DeleteMethod="Delete"
ID="ods" runat="server" 
SelectMethod="GetPagedList" SelectCountMethod="GetPagedListCount" 
TypeName="Pacem.Data.Adapter`1[[TestBLL,__Code]]">
    <SelectParameters>
        <asp:Parameter DefaultValue="GetPagedList" 
	Name="selectCommandName" Type="String" />
        <asp:Parameter Name="orderedParameters" Type="Object" />
    </SelectParameters>
</asp:ObjectDataSource>

My Entity class (VB.Net):

Public Class TestBLL

    Public Sub New(ByVal dummyVar As String)
        _dv = dummyVar
    End Sub

    <Field("ID", True, 0)> _
    Private _ID As Int32 = 0

    <Field("Description")> _
        Private _Desc As String = String.Empty

    <Field("DateTime")> _
        Private _Date As Date = DateTime.MinValue

    Private _dv As String = "not set"
    Public ReadOnly Property DummyProperty() As String
        Get
            Return _dv
        End Get
        Set(ByVal value As String)
            _dv = value
        End Set
    End Property

    Public Property ID() As Int32
        Get
            Return _ID
        End Get
        Set(ByVal value As Integer)
            _ID = value
        End Set
    End Property

    Public Property Description() As String
        Get
            Return _Desc
        End Get
        Set(ByVal value As String)
            _Desc = value
        End Set
    End Property

    Public Property DateTime() As Date
        Get
            Return _Date
        End Get
        Set(ByVal value As Date)
            _Date = value
        End Set
    End Property

End Class

And some code added to furtherly customize the scenario, and show the flexibility of the generic Adapter (VB.Net):

Protected Sub ods_ObjectCreating( _
        ByVal sender As Object, _
        ByVal e As ObjectDataSourceEventArgs) _
        Handles ods.ObjectCreating
    ' Cloning the adapter instance to customize it
    ' with new EventHandler for EntityConstructing event.
    ' The default Entity (T) contructor exploited has no parameters, 
    ' let's say that the TestBLL class hasn't constructors like that.
    Dim adapter As Pacem.Data.Adapter(Of TestBLL) = BLLAdapter.Clone()
    AddHandler adapter.EntityConstructing, _
        AddressOf Me.BLL_Adapter_EntityConstructing
    e.ObjectInstance = adapter
End Sub

Protected Sub ods_Selecting( _
        ByVal sender As Object, _
        ByVal e As ObjectDataSourceSelectingEventArgs) _
    Handles ods.Selecting
    ' The GetList and GetPagedList receive a sting representing the name of 
    ' the selectcommand to be used and a parameter array of objects, 
    ' in this case just a DateTime.
    ' (The signature of GetPagedList method exposes also 
    ' two Int32 parameters for paging purposals)
    If Not e.ExecutingSelectCount Then
        e.InputParameters("orderedParameters") = #8/5/2003#
    End If
End Sub

Protected Sub BLL_Adapter_EntityConstructing( _
        ByVal o As Object, _
        ByVal e As Pacem.Data.EntityConstructEventArgs(Of TestBLL))
    e.Entity = New TestBLL("my custom constructor parameter value")
End Sub

Private _BLLAdapter As Pacem.Data.Adapter(Of TestBLL) = Nothing
Private ReadOnly Property BLLAdapter() As Pacem.Data.Adapter(Of TestBLL)
    Get
        If _BLLAdapter Is Nothing Then
            _BLLAdapter = Pacem.Data.Adapter(Of TestBLL).Create( _
                Server.MapPath("TestBLLAdapter.xml"))
        End If
        Return _BLLAdapter
    End Get
End Property

Take care. Bye.

feedback
 

Syndicate

Author

Cristian Merighi facebook twitter google+ youtube

Latest articles

Top rated

Archive

Where am I?

Author

Cristian Merighi facebook twitter google+ youtube

I'm now reading

Feeds