GridView ObjectDataSource 适配器






3.67/5 (6投票s)
2007年2月2日
3分钟阅读

59894

333
在这篇简短的文章中,作者提到了两种技术,他使用这两种技术来允许将 GridView 映射到基于现有中间层对象构建的 DataTables。
引言
ASP.NET 2.0 中的 GridView
控件是一个非常强大的控件,我特别喜欢我们可以将 GridView
控件映射到对象数据源的方式。此外,我喜欢 GridView
如何在不需要代码的情况下启用排序和分页。非常好!将 GridView
映射到对象数据源的一个好处(在我看来)是它促进了分层架构。但是,如果您将 GridView
映射到对象数据源,您可能会在尝试对 GridView
进行排序时遇到以下异常
The data source 'objDataSource' does not support sorting
with IEnumerable data. Automatic sorting is only supported
with DataView, DataTable, and DataSet
现在,通过选择将 GridView
直接映射到 DataSet
而不是相关的应用程序对象,从而失去将数据封装在中间层对象中的所有巨大好处,这对我来说似乎有点荒谬。所有这些妥协,只是为了让排序可以在 GridView
中工作。在这篇简短的文章中,我想提到两种技术,我使用这两种技术来允许将 GridView
映射到基于现有中间层对象构建的 DataTable
。我倾向于将此视为伪适配器模式,它将我的模型对象转换为 DataTable
。这样做的好处是,我可以利用我之前编写的所有中间层逻辑,同时还可以实现 GridView
控件的强大功能,例如排序。这两种技术是
- 使用反射初始化中间层“模型”层对象。
- 使用反射将中间层“模型”层对象转换为
DataTable
。
在进入代码之前,我应该提到我的应用程序中通常存在的层。这将更容易概念化我在哪里采用上述技术。
- 模型层 – 此层包含封装数据的对象。此层由所有轻量级可序列化类组成,这些类仅声明属性。此层中没有任何方法。这些类用于通过应用程序的各个层传递数据。
- 控制器层 – 此层是我的 ASP.NET 应用程序和业务逻辑层之间的粘合剂。
- 业务逻辑层 – 业务逻辑层作用于模型层中的数据。此层还通过“要求”数据层对模型层对象执行 CRUD(创建、检索、更新和删除)操作来与数据逻辑层进行交互。
- 数据逻辑层 – 此层用于对模型层对象执行实际的 CRUD 操作。
我使用的第一种技术是在数据逻辑层中。一旦我从数据库中检索到 DataSet
,我就使用反射创建并初始化相关的模型层类。本质上,此方法遍历 DataSet
中一行的所有列,并在我的模型对象中调用相关的 set 方法。只有当我的模型对象具有与 DataSet
中列名匹配的属性名称时,才会发生调用。此方法的结果是初始化的模型层对象。
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
我使用的第二种技术是在控制器层中。简单地说,在控制器层中放置一个类,该类要求业务逻辑层将模型层对象转换为 DataTable
。这使我能够以一种间接的方式将我的 GridView
映射到我的模型对象。我说间接的方式是因为我真正做的只是获取一个模型层对象并将其转换为 DataTable
。这就是适配器模式发挥作用的地方。
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
摘要
使这成为可能的是反射。我附上了一个非常简单的 Web 应用程序,它使用了上面讨论的两种技术。请注意,在附加的源代码中,第一个网格在排序时会导致异常,而第二个网格像魅力一样工作。示例中规避异常的关键代码行是
Return myObject.ConvertToDataTable(myEmployees, _
GetType(IModelLayer.IEmployee))
这将返回 Employee 模型对象的 DataTable
表示,我的 GridView
可以很好地使用它。
联系作者:Brian Rush。