GridView ObjectDataSource Adapter






3.67/5 (6 votes)
Feb 2, 2007
3 min read

59364

319
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 GridView
s 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 GridView
s directly to DataSet
s 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 GridView
s to DataTable
s 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 DataTable
s. 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:
- Using reflection to initialize middle tier "model" layer objects.
- Using reflection to convert middle tier "model" layer objects into
DataTable
s.
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.
- 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.
- Controller Layer – This layer is the glue between my ASP.NET application and the Business Logic Layer.
- 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.
- 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.
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.
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:
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.