在Web项目中MS提供了ObjectDataSource,利用它配合MyOrm可以方便的实现分页、排序等。
简单说一下ObjectDataSource,这个东东感觉多少有点变扭。首先它需要指定一个BusinessObject,通过给Select、Update、Insert等操作指定BusinessObject中对应的方法,页面的操作通过反射调用对应的方法。这里MS提供了DataObjectAttribute和DataObjectMethodAttribute来标识BusinessObject以及其中的方法对应哪个操作。其实我倒觉得不如给BusinessObject定义一个接口来的省事,省得在界面中设置一堆参数。另外一个,BusinessObject如果不是静态类,ObjectDataSource每次都会创建一个对象,而不能指定某个现有的BusinessObject变量。这导致了像NHibernate、Spring之类底层的框架完全不可用,另外每次创建对象对效率也不利。
为了解决这个问题,需要专门为ObjectDataSource定义新的BusinessObject,在ObjectDataSource和底层业务之间搭一座桥。
在MyOrm的例子中,定义了ObjectSource<T>:
- [DataObject]
- public class ObjectSource<T>
- {
- private IObjectViewDAO<T> objectViewDAO;
- public IObjectViewDAO<T> ObjectViewDAO
- {
- get
- {
- if (objectViewDAO == null) objectViewDAO = (IObjectViewDAO<T>)NorthwindFactory.GetObjectViewDAO(typeof(T));
- return objectViewDAO;
- }
- }
- [DataObjectMethod(DataObjectMethodType.Select, true)]
- public List<T> Select(Condition condition)
- {
- return ObjectViewDAO.Search(condition);
- }
- [DataObjectMethod(DataObjectMethodType.Select, false)]
- public List<T> Select(Condition condition, int startRowIndex, int maximumRows)
- {
- return ObjectViewDAO.SearchSection(condition, startRowIndex, maximumRows, null, false);
- }
- [DataObjectMethod(DataObjectMethodType.Select, false)]
- public List<T> Select(Condition condition, int startRowIndex, int maximumRows, string orderBy)
- {
- bool desc = false;
- if (!String.IsNullOrEmpty(orderBy))
- {
- string[] args = orderBy.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
- orderBy = args[0];
- desc = args.Length > 1 && String.Compare(args[1], "desc", true) == 0;
- }
- return ObjectViewDAO.SearchSection(condition, startRowIndex, maximumRows, orderBy, desc);
- }
- public int Count(Condition condition)
- {
- return ObjectViewDAO.Count(condition);
- }
- }
ObjectSource的工作很简单,就是把ObjectDataSource的输入转化为底层可接受的输入,而且创建ObjectSource的开销也很小。这里ObjectSource只定义了查询,没有增删改操作,如果需要可以自己加下。
ObjectSource<T>是泛型,并不能直接被ObjectDataSource使用,还需要为每个实体类定义对应的ObjectSource。
- public class CategoriesSource : ObjectSource<Categories> { }
- public class CustomerCustomerDemoSource : ObjectSource<CustomerCustomerDemo> { }
- public class CustomerDemographicsSource : ObjectSource<CustomerDemographics> { }
- public class CustomersSource : ObjectSource<Customers> { }
- public class EmployeesSource : ObjectSource<Employees> { }
- public class EmployeeTerritoriesSource : ObjectSource<EmployeeTerritories> { }
- public class OrderDetailsSource : ObjectSource<OrderDetails> { }
- public class OrdersSource : ObjectSource<Orders> { }
- public class ProductsSource : ObjectSource<Products> { }
- public class RegionSource : ObjectSource<Region> { }
- public class ShippersSource : ObjectSource<Shippers> { }
- public class SuppliersSource : ObjectSource<Suppliers> { }
- public class TerritoriesSource : ObjectSource<Territories> { }
- public class CustomerCustomerDemoViewSource : ObjectSource<CustomerCustomerDemoView> { }
- public class EmployeesViewSource : ObjectSource<EmployeesView> { }
- public class EmployeeTerritoriesViewSource : ObjectSource<EmployeeTerritoriesView> { }
- public class OrderDetailsViewSource : ObjectSource<OrderDetailsView> { }
- public class OrdersViewSource : ObjectSource<OrdersView> { }
- public class ProductsViewSource : ObjectSource<ProductsView> { }
- public class TerritoriesViewSource : ObjectSource<TerritoriesView> { }
现在可以在页面中很方便的使用ObjectDataSource了。
例如需要创建一个可排序可分页的GridView:
首先建一个GridView;
然后给GridView选择数据源,选择添加新数据源;
在向导中选择创建Object类型的数据源,在BusinessObject选择界面中会出现已经定义好的ObjectSource(ObjectSource定义后需要重新编译一下才会出现),选择你所需要的。
然后next、next最后finish就可以了。
现在GridView已经可以显示内容了,但是排序、分页还没实现。还需要多2个步骤:
设置ObjectDataSource的EnablePaging为true,SelectCountMethod为Count,SortParameterName为orderBy(ObjectSource中的Select方法的对应参数名,MaximumRowsParameterName和StartRowIndexParameterName的默认值和ObjectSource中的参数名一致,就不需要设置了);
最后把GridView的AllowPaging和AllowSorting设为true就可以了。
下面是生成的aspx页面,后台aspx.cs不需要添加代码。
- <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True"
- AutoGenerateColumns="False" DataSourceID="ObjectDataSource1">
- <Columns>
- <asp:BoundField DataField="Category_CategoryName" HeaderText="Category_CategoryName"
- SortExpression="Category_CategoryName" />
- <asp:BoundField DataField="Category_Description" HeaderText="Category_Description"
- SortExpression="Category_Description" />
- <asp:BoundField DataField="Supplier_CompanyName" HeaderText="Supplier_CompanyName"
- SortExpression="Supplier_CompanyName" />
- <asp:BoundField DataField="Supplier_ContactName" HeaderText="Supplier_ContactName"
- SortExpression="Supplier_ContactName" />
- <asp:BoundField DataField="Supplier_ContactTitle" HeaderText="Supplier_ContactTitle"
- SortExpression="Supplier_ContactTitle" />
- <asp:BoundField DataField="Supplier_Address" HeaderText="Supplier_Address" SortExpression="Supplier_Address" />
- <asp:BoundField DataField="Supplier_City" HeaderText="Supplier_City" SortExpression="Supplier_City" />
- <asp:BoundField DataField="Supplier_Region" HeaderText="Supplier_Region" SortExpression="Supplier_Region" />
- <asp:BoundField DataField="Supplier_PostalCode" HeaderText="Supplier_PostalCode"
- SortExpression="Supplier_PostalCode" />
- <asp:BoundField DataField="Supplier_Country" HeaderText="Supplier_Country" SortExpression="Supplier_Country" />
- <asp:BoundField DataField="Supplier_Phone" HeaderText="Supplier_Phone" SortExpression="Supplier_Phone" />
- <asp:BoundField DataField="Supplier_Fax" HeaderText="Supplier_Fax" SortExpression="Supplier_Fax" />
- <asp:BoundField DataField="Supplier_HomePage" HeaderText="Supplier_HomePage" SortExpression="Supplier_HomePage" />
- <asp:BoundField DataField="ProductID" HeaderText="ProductID" SortExpression="ProductID" />
- <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
- <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" SortExpression="SupplierID" />
- <asp:BoundField DataField="CategoryID" HeaderText="CategoryID" SortExpression="CategoryID" />
- <asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit" SortExpression="QuantityPerUnit" />
- <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice" SortExpression="UnitPrice" />
- <asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock" SortExpression="UnitsInStock" />
- <asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder" SortExpression="UnitsOnOrder" />
- <asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel" SortExpression="ReorderLevel" />
- <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" SortExpression="Discontinued" />
- </Columns>
- </asp:GridView>
- <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" EnablePaging="True" OldValuesParameterFormatString="original_{0}"
- SelectCountMethod="Count" SelectMethod="Select" SortParameterName="orderBy" TypeName="Northwind.ProductsViewSource">
- <SelectParameters>
- <asp:Parameter Name="condition" Type="Object" />
- </SelectParameters>
- </asp:ObjectDataSource>
如果ObjectDataSource能设计的再好些的话整个步骤会更方便。目前为止Select方法的condition参数都是为空的,也就是说只是查询所有的内容。如果需要使用查询条件的,可以有3个方法:
1、自定义查询条件控件,并提供一个类型为Condition的属性,然后把ObjectDataSource的SelectParameters中的condition设为ControlParameter,并指定ControlID为自定义的查询条件控件。
2、在ObjectDataSource的Selecting事件中,通过程序给e.InputParameters["condition"]赋值。
3、自定义包含Condition的Parameter,关于自定义Parameter可以参考msdn:Parameter Class。
示例代码可以到CodePlex下载,包含在Samples解决方案里。