一步一步学习ObjectDataSource(1)
ASP.NET2.0给出了ObjectDataSource控件,结果使得Code变成了属性的设置,本文一步一步介绍ObjectDataSource的使用。
1)基本使用
绑定到数据访问层
数据访问层组件封装通过对 ADO.NET的封装来查询和修改数据库。它通常的方法是创建 ADO.NET 连接和执行SQL命令来访问数据库。典型的数据访问层组件可按如下方式公开:
public class MyDataBllLayer { public DataView GetRecords(); public int UpdateRecord(int recordID, String recordData); public int DeleteRecord(int recordID); public int InsertRecord(int recordID, String recordData); }
如上,基本上在业务逻辑访问层定义对数据库里的记录进行操作,上面就定义了GetRecords、UpdateRecord、DeleteRecord和InsertRecord四个方法来读取、更新、删除和插入数据库里的数据,这些方法基本上是根据SQL里的Select、Update、Delete和Insert语句而定义。
和上面方法相对应, ObjectDataSource提供了四个属性来设置该控件引用的数据处理,可以按照如下方式关联到该类型,代码如下
<asp:ObjectDataSource TypeName="MyDataLayer" runat="server" SelectMethod="GetRecords" UpdateMethod="UpdateRecord" DeleteMethod="DeleteRecord" InsertMethod="InsertRecord" />
这里的SelectMethon设置为MyDataBllLayer里的GetRecords()方法,UpdateMethod设置为UpdateRecord方法,DeleteMethod设置为DeleteRecord,以及InsertMethod设置为InsertRecord方法。在使用时需要注意ObjectDataSource旨在以声明的方式简化数据的开发,所以这里设置SelectMethod的值为GetRecords而不是GetRecords(),也就是不带括号。
在上面GetRecords()的定义时,可以看到该方法返回的类型是DataView,由于ObjectDataSource将来需要作为绑定控件的数据来源,所以它的返回类型必须如下的返回类型之一:
Ienumerable、DataTable、DataView、DataSet或者Object。
除此以外,ObjectDataSource还有一个重要的属性TypeName,ObjectDataSource控件使用反射技术来从来从业务逻辑程序层的类对象调用相应的方法,所以TypeName的属性值就是用来标识该控件工作时使用的类名称,通常TypeName需要包含命名空间,假设上面代码段为
namespace XX.YY { public class MyDataBllLayer { public DataView GetRecords(); public int UpdateRecord(int recordID, String recordData); public int DeleteRecord(int recordID); public int InsertRecord(int recordID, String recordData); } }
那么TypeName应该设置为XX.YY.MyDataLayer
<asp:ObjectDataSource TypeName="XX.YY.MyDataLayer" runat="server" SelectMethod="GetRecords" UpdateMethod="UpdateRecord" DeleteMethod="DeleteRecord" InsertMethod="InsertRecord" />
下面的例子演示了ObjectDataSource的基本使用。
在该例子里定义了一个数据业务逻辑层来处理数据库链接和业务逻辑,这些处理都是有App_Code文件夹下的NorthwndDB.cs文件完成,先大致浏览一下该文件里定义的方法:
using System; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.Collections.Generic; using System.Web.UI; using System.Web.UI.WebControls; public class EmployeeInfo { private string _connectionString; public EmployeeInfo() { _connectionString = ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString; } public SqlDataReader GetEmployees() { SqlConnection con = new SqlConnection(_connectionString); string selectString = "SELECT EmployeeID,LastName,Firstname,Title,Address,City,Region,PostalCode FROM Employees ORDER BY EmployeeID"; SqlCommand cmd = new SqlCommand(selectString, con); con.Open(); SqlDataReader dtr = cmd.ExecuteReader(CommandBehavior.CloseConnection); return dtr; } public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode) { SqlConnection con = new SqlConnection(_connectionString); string updateString = "UPDATE Employees SET Address=@Address,City=@City WHERE EmployeeID=@EmployeeID"; SqlCommand cmd = new SqlCommand(updateString, con); cmd.Parameters.AddWithValue("@Address", Address); cmd.Parameters.AddWithValue("@City", City); cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } public void DeleteEmployee(int EmployeeId) { SqlConnection con = new SqlConnection(_connectionString); string deleteString = "DELETE Employees WHERE EmployeeID=@EmployeeID"; SqlCommand cmd = new SqlCommand(deleteString, con); cmd.Parameters.AddWithValue("@EmployeeId", EmployeeId); con.Open(); cmd.ExecuteNonQuery(); con.Close(); } }
在这段代码里,定义了GetEmployees方法来获取所有员工级别信息,UpdateEmployee方法更新员工的基本资料,DeleteEmployee方法用来删除员工资料,这样就可以在ObjectDataSource1.aspx里使用如下代码调用业务逻辑的处理,如下
<asp:GridView ID="GridView1" DataSourceID="ObjectDataSource1" DataKeyNames="EmployeeId" AutoGenerateColumns="true" AutoGenerateEditButton="True" AutoGenerateDeleteButton="True" Runat="Server" CellPadding="4" Font-Names="Verdana" Font-Size="X-Small" ForeColor="#333333" GridLines="None"> … … </asp:GridView> <asp:ObjectDataSource ID="ObjectDataSource1" TypeName="EmployeeInfo" SelectMethod="GetEmployees" UpdateMethod="UpdateEmployee" DeleteMethod="DeleteEmployee" Runat="Server"> <UpdateParameters> <asp:Parameter Name="EmployeeId" Type="Int32" /> <asp:Parameter Name="Address" /> <asp:Parameter Name="City" /> </UpdateParameters> </asp:ObjectDataSource>
上面使用了GrieView控件后面会有专门介绍,这里我们专注ObjectDataSource控件的使用,在该控件里设置 TypeName为"EmployeeInfo"表示将来调用的类名称为EmployeeInfo,调用SelectMethond/UpdateMethod/DeleteMethod调用的的方法分别是EmployeeInfo类里的GetEmployees/UpdateEmployee/DeleteEmployee方法。
具体运行可以自己试验。从运行结果里单击“Edit”可以更新员工的资料,单击“Delete”将删除员工的资料。
在运行上面的例子里,可能看到UpdateEmployee的定义如下:
public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode) { ... ... cmd.Parameters.AddWithValue("@Address", Address); cmd.Parameters.AddWithValue("@City", City); cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId); ... ... }
这段代码表示更新员工资料时,其实只更新了员工的地址(Address)和所在的程序(City),而对于姓名(FirstName,LastName)、职称(Title)等并没有更新。
既然FistName、LastName、Title等并没有更新,为什么不将UpdateEmployee写成如下方式呢?
public void UpdateEmployee(int EmployeeId string Address, string City,) { ... ... cmd.Parameters.AddWithValue("@Address", Address); cmd.Parameters.AddWithValue("@City", City); cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId); ... ... }
也就是只保留需要的三个参数而将其它变量不写,如果这样做将发生错误如下:
提示错误为:ObjectDataSource1找不到一个包含Address,City,LastName,Firstname,Title,Region,PostalCode和Employee参数的非泛型方法.
这是因为ObjectDataSource1默认讲根据Select语句,生成Update,Insert和Delete。仔细看一下上面GetEmployees()的SQL语句的写法:
SELECT EmployeeID,LastName,Firstname,Title,Address,City,Region,PostalCode FROM Employees ORDER BY EmployeeID
Select共有8个字段,因此,你在UpdateEmployee必须定义一个方法,也同时包含这8个字段。另外,ObjectDataSource1根据参数名(而不是类型)进行匹配查找。也就是
他默认查找UpdateEmployee方法,同时,该方法有8个参数,而且这8个参数的名称是EmployeeID,LastName,Firstname,Title,Address,City,Region,PostalCode,
也就是 public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode) 函数。
在查找中,参数顺序不是很重要,例如你可以吧EmployeeId放到后面,即
public void UpdateEmployee( string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode,int EmployeeId)
但是,如果你方法更改为
public void UpdateEmployee(int EmpId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode)
则出现错误,因此上面已经说了,他是根据参数名,进行查找的。
了解了上面的说明,你可以对UpdateEmployee进行重载。代码如下
public void UpdateEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode) { UpdateEmployee(EmployeeId,Address,City) } public void UpdateEmployee(int EmployeeId, string Address, string City ) { SqlConnection con = new SqlConnection(_connectionString); string updateString = "UPDATE Employees SET Address=@Address,City=@City WHERE EmployeeID=@EmployeeID"; SqlCommand cmd = new SqlCommand(updateString, con); cmd.Parameters.AddWithValue("@Address", Address); cmd.Parameters.AddWithValue("@City", City); cmd.Parameters.AddWithValue("@EmployeeID", EmployeeId); con.Open(); cmd.ExecuteNonQuery(); con.Close(); }
通过重载UpdateEmployee方法,便于数据的扩展和维护。
接下来说一下Delete方法
public void DeleteEmployee(int EmployeeId) { }
熟悉数据库的用户都知道,要删除一条记录,只要知道主键即可,因此在删除Employee时,只要知道EmployeeId即可,并不需要传递Name,City等参数。这就是为什么DeleteEmployee只要一个参数的原因。
但是,如何告诉ObjectDataSourceID, Employee的主键是EmployeeId而不是Usename呢?
这个功能是GridView里实现的,请仔细查看GridView的定义:
<asp:GridView
ID="GridView1"
DataSourceID="ObjectDataSource1"
DataKeyNames="EmployeeId"
AutoGenerateColumns="true"
AutoGenerateEditButton="True"
AutoGenerateDeleteButton="True"
Runat="Server" CellPadding="4" Font-Names="Verdana" Font-Size="X-Small" ForeColor="#333333" GridLines="None">
… …
你可以看到,代码里设置了DataKeyNames为EmployeeId,这就告诉了ObjectDatasourceId,当调用Delete方法时,只要传递一个主键EmployeeID即可,不需要把DeleteEmployee定义为
DeleteEmployee(int EmployeeId, string LastName, string Firstname, string Title, string Address, string City, String Region, string PostalCode)
。了解了上面的Update和Delete,你应该很容易理解Insert方法了。