Resumé

Adapter(Of T) Generic e CRUD in .Net

Cristian Merighi () 0,00

Un oggetto per centralizzare tutta la logica di CRUDding associata a classi e liste di classi Business Logic custom. Si tratta di un primo vero step stabile, in attesa di generare DynamicMethods e codice a runtime...
Questo articolo è da considerarsi obsoleto. Alcune funzionalità potrebbero non essere più disponibili e non è possibile aggiungere commenti.

Sono piuttosto orgoglioso di ciò che ho appena finito di confezionare... il mio Pacem.Data.Adapter<T> sembra potermi assicurare (già in questa sua prima forma) notevoli risparmi di tempo nei processi di scrittura di codice dell'immediato futuro. E allo stesso tempo mi garantirà più solidità e affidabilità grazie alla mole di test in atto sulle sue caratteristiche!

Il tutto nacque allorché cominciai a mostrare insoddisfazione nel ripetere, applicativo dopo applicativo, le stesse righe di codice per "trasportare" contenuti dal Database alla GUI - passando per i vari livelli DALC (Data Access Layer Components), DAL (Data Access Layer) and BLL (Business Logic Layer)... una, due, tre volte! ...basta.

L'intento era quello di rendere necessarie, all'interno dei miei applicativi data-driven, le sole query SQL e, ovviamente, le righe di markup (o analogo) per le interfacce personalizzate.

Iniziai (vedi articolo relativo) creando classi abstract con implementazioni base per agevolarne il popolamento.
"..mmmh, sì, discreto ma solo un minor step nel percorso verso la totale gestione automatizzata del CRUDding..."

Allora accoppiai queste classi con oggetti particolari che battezzai Adapters (che fantasia) coi quali potevo attivare le operazioni di inserimento, modifica e cancellazione per le singole istanze di entity BLL (vedi quest'altro articolo).
"...sì, meglio! Ma così le logiche di CRUD sono condivise tra diversi oggetti, alla faccia dell'incapsulamento, non un buon approccio al design e - soprattutto - mancano ancora le funzionalità di selezione per recuperare le liste enumerabili di questi custom Business Layer objects!"

Ecco quindi il mio Adapter<T> generic (o Adapter(Of T) per chi preferisce la sintassi VB).
Esso è l'unico delegato a gestire i dati delle Enities Business Logic, sia nella loro singolarità sia nelle liste da essicomposte, il tutto con un semplice mapping dei campi del database su specifiche properties/fields contrassegnati da Pacem.Reflection.FieldAttribute attributes (custom attributes).

La logica è schematizzata nella seguente figura:

Class Diagram

La costruzione dell'Adapter può essere effettuata a partire da file xml tipo questo:

<?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>

Si tratta di un semplice esempio, si può aver a che fare con Adapter ben più complessi nei quali sono comprese persino le funzioni di custom paging per venire incontro alle features dei DataSource WebControls ASP.Net 2.0.
Qualche riga di codice per vedere come si sfrutta il mio Adapter...

Ecco un ObjectDataSource WebControl (poniamo associato ad un GridView); le righe sotto sono totalmente esaustive per le operazioni di modifica, cancellazione, selezione e paginazione!
(prego notare la formattazione di un tipo generic, evidenziata, ed il relativo carattere backtick "`". Vedi msdn reference).

<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>

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

E qualche riga di codice per una customizzazione ulteriore atta a mostrare la flessibilità dell'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

Autore

Cristian Merighi facebook twitter google+ youtube

Ultimi articoli

Top rated

Archivio

Dove sono?

Autore

Cristian Merighi facebook twitter google+ youtube

Le mie letture

Feeds