Click here to Skip to main content
15,867,330 members
Articles / Web Development / ASP.NET
Article

GridView ObjectDataSource Adapter

Rate me:
Please Sign up or sign in to vote.
3.67/5 (6 votes)
2 Feb 20073 min read 58.5K   319   29   7
In this brief article, the author mentions two techniques that he uses to allow for mapping GridViews to DataTables that are built upon existing middle tier objects.

Introduction

The GridView control in ASP.NET 2.0 is a very robust control, and I particularly like how we can map GridView controls to object data sources. Furthermore, I appreciate how the GridView enables sorting and paging with no code required. Very nice! A benefit of mapping GridViews to object data sources (in my opinion) is that it promotes a tiered architecture. However, if you map a GridView to an object data source, you may encounter the following exception when trying to sort a GridView:

The data source 'objDataSource' does not support sorting 
with IEnumerable data. Automatic sorting is only supported 
with DataView, DataTable, and DataSet

Now, it seems a bit absurd to me to lose all the great benefits of encapsulating data within middle tier objects by opting to map GridViews directly to DataSets and not the pertinent application objects. All of this compromise, just so sorting can work within the GridView. In this brief article, I want to mention two techniques that I use to allow for mapping GridViews to DataTables that are built upon existing middle tier objects. I tend to think of this as a pseudo adapter pattern that converts my model objects into DataTables. A benefit of this is that I can leverage all my previously written middle tier logic while also realizing the great features of the GridView control like sorting. The two techniques are:

  1. Using reflection to initialize middle tier "model" layer objects.
  2. Using reflection to convert middle tier "model" layer objects into DataTables.

Prior to getting into the code, I should mention the layers I typically have in my application. This will make it easier to conceptualize where I employ the techniques above.

  1. Model Layer – This layer holds objects that encapsulate data. This layer consists of all lightweight serializable classes that declare properties only. No methods whatsoever in this layer. These are the classes that I use to pass data through the various layers of the application.
  2. Controller Layer – This layer is the glue between my ASP.NET application and the Business Logic Layer.
  3. Business Logic Layer – The Business Logic Layer acts on the data within the model layer. This layer also interfaces with the data logic layer by "asking" the data layer to perform CRUD (Create, Retrieve, Update, and Delete) operations on Model Layer objects.
  4. Data Logic Layer – This layer is used to perform the actual CRUD operations on the Model Layer objects.

The first technique that I use is within the Data Logic Layer. Once I retrieve a DataSet from a database, I create and initialize the pertinent Model Layer class using reflection. In essence, this method iterates through all the columns of a row in a DataSet and invokes the pertinent set methods within my model object. The invocation occurs only when my model object has property names the match the column names within the DataSet. The result of this method is an initialized Model Layer object.

VB
Public Function InitializeFromDataRow(ByVal aDataRow _
       As System.Data.DataRow, ByVal aType _
       As System.Type) As Object
       Implements IDLL.IBaseDataObject.InitializeFromDataRow
    Try
        Dim props As PropertyInfo()
        Dim myObject As Object
        ' Create our object through reflection
        myObject = Activator.CreateInstance(aType)
        Dim p As PropertyInfo
        props = aType.GetProperties()
        'Now go set all the public attributes based 
        'on the columns and values within the datatable
        For Each p In props
               Dim params(0) As Object
               'Make sure we have a column in dataset 
               'for the attribute we are trying to set.
               If aDataRow.Table.Columns.Contains(p.Name) = True Then
                   params(0) = aDataRow.Item(p.Name)
                   p.GetSetMethod.Invoke(myObject, params)
               End If
        Next
        Return myObject
    Catch ex As Exception
        Throw ex
    End Try
    Return Nothing    
End Function

The second technique that I use is in the Controller Layer. Simply put a class within the Controller Layer that asks the Business Logic Layer to convert a Model Layer object into a DataTable. This enables me to map my GridView to my model objects in a round about way. I say a round about way because all I am really doing is taking a Model Layer object and converting it to a DataTable. This is where the adapter like pattern comes into play.

VB
Public Function ConvertToDataTable(ByVal list As _
       System.Collections.IList, _
       ByVal aType As System.Type) As DataTable
    Try
        Dim aDataTable As New DataTable       
        Dim props As PropertyInfo()
        Dim p As PropertyInfo
        props = aType.GetProperties()
        Dim anObject As Object
        'Create all the pertinent columns
        For Each p In props
            aDataTable.Columns.Add(New _
                 DataColumn(p.Name, p.PropertyType))
        Next
        'Now go add all the data into datatable.
        For Each anObject In list
           Dim row(props.Length - 1) As Object
           Dim i As Integer
           i = 0
           row(props.Length - 1) = New Object()
           For Each p In props
                   row(i) = p.GetValue(anObject, Nothing)
                   i = i + 1
           Next
           aDataTable.Rows.Add(row)
        Next
        Return aDataTable
    Catch ex As Exception
        Throw ex
    End Try
        Return Nothing    
End Function

Summary

What makes this possible is reflection. I have attached a very simple web application that makes use of the two techniques discussed above. Note, in the attached source code, the first grid results in an exception upon sorting while the second grid works like a charm. The key line of code in the example that circumvents the exception is:

VB
Return myObject.ConvertToDataTable(myEmployees, _
                GetType(IModelLayer.IEmployee))

This returns a DataTable representation of an Employee Model object that my GridView can play nicely with.

Contact the author: Brian Rush.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralAlternative methods Pin
awstam24-Sep-07 0:08
awstam24-Sep-07 0:08 
QuestionWhat about System.Nullable types? Pin
Mufasa24517-Mar-07 9:11
Mufasa24517-Mar-07 9:11 
AnswerRe: What about System.Nullable types? Pin
Brian Rush20-Mar-07 3:28
Brian Rush20-Mar-07 3:28 
Yep. Good point. Once I put my app into production I quickly realized that. This is what I changed to account for nulls

Protected Function InitializeFromDataRow(ByVal aDataRow As System.Data.DataRow, ByVal aType As System.Type) As OptimAZ.IModelLayer.IBaseModel Implements IDLL.IBaseDataObject.InitializeFromDataRow
Try
Dim myObject As Object
' Create our object through reflection
myObject = Activator.CreateInstance(aType)
Dim props As PropertyInfo()
Dim p As PropertyInfo
props = aType.GetProperties()
'Now go set all the public attributes based on the columns and values within the datatable
For Each p In props
Dim params(0) As Object
'Make sure we have a column in dataset for the attribute we are trying to set.
If aDataRow.Table.Columns.Contains(p.Name) = True Then
params(0) = aDataRow.Item(p.Name)
Dim value As Object
value = params(0)
If Not (value Is System.DBNull.Value) Then
p.GetSetMethod.Invoke(myObject, params)
End If
End If
Next
Return myObject
Catch ex As Exception
Throw New Exception(ex.Message, ex)
End Try
Return Nothing
End Function
GeneralJust what I've been looking for Pin
Mr_Hosed9-Feb-07 7:09
Mr_Hosed9-Feb-07 7:09 
GeneralRe: Just what I've been looking for Pin
Brian Rush10-Feb-07 7:44
Brian Rush10-Feb-07 7:44 
Generalvery tiny utility, but very much useful.. Pin
Ruchit S.7-Feb-07 3:01
Ruchit S.7-Feb-07 3:01 
GeneralRe: very tiny utility, but very much useful.. Pin
Brian Rush7-Feb-07 7:16
Brian Rush7-Feb-07 7:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.