ObjectDataSource 控件基于 SelectMethod、InsertMethod、UpdateMethod 或 DeleteMethod 属性中所标识的方法名称以及组成业务对象方法签名的参数名来调用业务对象方法。在业务对象中创建方法时,必须确保业务对象方法所接受的参数名和类型与 ObjectDataSource 控件传递的参数名和类型匹配。(参数顺序并不重要。)
一、使用参数
同所有的数据源控件一样,ObjectDataSource 控件在运行时接受输入参数,并在参数集合中对参数进行管理。每一项数据操作都有一个相关的参数集合。对于选择操作,可以使用 SelectParameters 集合;对于更新操作,可以使用 UpdateParameters 集合,依此类推。
可以为每个参数指定名称、类型、方向和默认值。对于从特定对象(例如,控件、会话变量或用户配置文件)获取值的参数,需要设置其他属性。例如,对于 ControlParameter 对象,需要设置 ControlID 属性以标识要获取参数值的控件,以及设置 PropertyName 属性以标识包含参数值的属性。
下面的代码示例演示一个可以通过 ObjectDataSource 控件调用的 Select 方法。该方法从数据源获取参数并选择单个记录。
[DataObjectMethod(DataObjectMethodType.Select)]
public static DataTable GetEmployee(int EmployeeID)
{
if (!_initialized) { Initialize(); }
SqlConnection conn = new SqlConnection(_connectionString);
SqlDataAdapter da =
new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode FROM Employees WHERE EmployeeID = @EmployeeID", conn);
da.SelectCommand.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
DataSet ds = new DataSet();
try
{
conn.Open();
da.Fill(ds, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];
return null;
}
二、为 Insert、Update 和 Delete 方法传递参数
ObjectDataSource 控件基于 InsertParameters、UpdateParameters 和 DeleteParameters 集合,分别确定要为插入、更新或删除操作调用的方法。另外,ObjectDataSource 控件将基于支持自动更新、插入和删除操作的数据绑定控件(例如 GridView 或 FormView 控件)所传递的值自动创建参数。
下面的代码示例演示一个可由 ObjectDataSource 控件调用的方法。该方法可以更新 Northwind 示例数据库中的雇员信息。
[DataObjectMethod(DataObjectMethodType.Update)]
public static bool UpdateEmployee(int EmployeeID, string FirstName, string LastName,
string Address, string City, string Region, string PostalCode)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");
if (String.IsNullOrEmpty(LastName))
throw new ArgumentException("LastName cannot be null or an empty string.");
if (Address == null) { Address = String.Empty; }
if (City == null) { City = String.Empty; }
if (Region == null) { Region = String.Empty; }
if (PostalCode == null) { PostalCode = String.Empty; }
if (!_initialized) { Initialize(); }
SqlConnection conn = new SqlConnection(_connectionString);
SqlCommand cmd = new SqlCommand("UPDATE Employees " +
" SET FirstName=@FirstName, LastName=@LastName, " +
" Address=@Address, City=@City, Region=@Region, " +
" PostalCode=@PostalCode " +
" WHERE EmployeeID=@EmployeeID", conn);
cmd.Parameters.Add("@FirstName", SqlDbType.VarChar, 10).Value = FirstName;
cmd.Parameters.Add("@LastName", SqlDbType.VarChar, 20).Value = LastName;
cmd.Parameters.Add("@Address", SqlDbType.VarChar, 60).Value = Address;
cmd.Parameters.Add("@City", SqlDbType.VarChar, 15).Value = City;
cmd.Parameters.Add("@Region", SqlDbType.VarChar, 15).Value = Region;
cmd.Parameters.Add("@PostalCode", SqlDbType.VarChar, 10).Value = PostalCode;
cmd.Parameters.Add("@EmployeeID", SqlDbType.Int).Value = EmployeeID;
try
{
conn.Open();
if (cmd.ExecuteNonQuery() == 0)
return false;
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
return true;
}
该代码示例假定已将 ObjectDataSource 控件的 ConflictDetection 属性设置为 OverwriteChanges。如果 ConflictDetection 属性设置为 CompareAllValues,业务对象方法必须接受数据字段原始值的参数。可以使用 OldValuesParameterFormatString 属性来区分当前值和原始值的参数。将 OldValuesParameterFormatString 属性设置为一个字符串表达式,该表达式用于设置原始值参数名称的格式,其中 {0} 字符表示字段名称。例如,如果将 OldValuesParameterFormatString 属性设置为 original_{0},名为 FirstName 的字段的当前值将由一个名为 FirstName 的参数传入,该字段的原始值将由一个名为 original_FirstName 的参数传入。
三、标识排序和分页参数
除了为 Select 业务对象方法指定 SelectParameters 对象之外,还可以包括排序和分页参数。这样您就可以对数据源对象中的数据进行排序,并将从数据源对象返回的结果限定为只返回所请求的数据页。
3.1、标识排序参数
使用 ObjectDataSource 控件的 SortParameterName 属性,可以为 Select 业务对象方法指定排序参数。SortParameterName 属性标识用于向业务对象方法传递排序列名称的参数名称。该参数为类型字符串。
某些数据绑定控件(例如 GridView 控件)可以自动向 ObjectDataSource 控件传递排序参数。在将支持排序的数据绑定控件绑定到 ObjectDataSource 控件时,该数据绑定控件将传递一个排序表达式,标识要用于对结果进行排序的数据列。例如,GridView 控件通过其 SortExpression 属性传递排序值。ObjectDataSource 控件基于为其传递的排序表达式,设置由 SortParameterName 属性所标识的参数的值。排序表达式可指定一个以上的列;指定多个列时,列名以逗号分隔。若要指定按降序排序,可以在排序表达式的排序列名称后加上 DESC 修饰符。例如,对于将 LastName 和 FirstName 列标识为排序依据列的排列表达式,使用“LastName, FirstName”可以按升序排序,使用“LastName, FirstName DESC”可以按降序排序。
3.2标识分页参数
可以为 Select 方法指定其他参数,标识要返回的数据页。ObjectDataSource 控件支持两个标识分页参数的属性:
·StartRowIndexParameterName 属性,标识在业务对象的 Select 方法中用于指定数据页起始行的参数的名称。
·MaximumRowsParameterName 属性,标识在业务对象的 Select 方法中用于指定数据页中的行数的参数名称。
StartRowIndexParameterName 和 MaximumRowsParameterName 属性所标识的参数都是 Int32 类型。
下面的代码示例演示一个 ObjectDataSource 控件,该控件配置为向指定业务对象的 Select 方法传递排序和分页参数:
<asp:ObjectDataSource
ID="EmployeesObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SortParameterName="SortColumns"
EnablePaging="true"
StartRowIndexParameterName="StartRecord"
MaximumRowsParameterName="MaxRecords"
SelectMethod="GetAllEmployees" >
</asp:ObjectDataSource>
下面的代码示例演示在上述示例中调用的 Select 业务对象方法。该业务对象方法从 Northwind 示例数据库中返回数据页,并按指定顺序排序。
public static void Initialize()
{
// Initialize data source. Use "Northwind" connection string from configuration.
if (ConfigurationManager.ConnectionStrings["Northwind"] == null ||
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString.Trim() == "")
{
throw new Exception("A connection string named 'Northwind' with a valid connection string " +
"must exist in the <connectionStrings> configuration section for the application.");
}
_connectionString =
ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
_initialized = true;
}
// Select all employees.
[DataObjectMethod(DataObjectMethodType.Select, true)]
public static DataTable GetAllEmployees(string sortColumns, int startRecord, int maxRecords)
{
VerifySortColumns(sortColumns);
if (!_initialized) { Initialize(); }
string sqlCommand = "SELECT EmployeeID, LastName, FirstName, Address, City, Region, PostalCode FROM Employees ";
if (sortColumns.Trim() == "")
sqlCommand += "ORDER BY EmployeeID";
else
sqlCommand += "ORDER BY " + sortColumns;
SqlConnection conn = new SqlConnection(_connectionString);
SqlDataAdapter da = new SqlDataAdapter(sqlCommand, conn);
DataSet ds = new DataSet();
try
{
conn.Open();
da.Fill(ds, startRecord, maxRecords, "Employees");
}
catch (SqlException e)
{
// Handle exception.
}
finally
{
conn.Close();
}
if (ds.Tables["Employees"] != null)
return ds.Tables["Employees"];
return null;
}
//////////
// Verify that only valid columns are specified in the sort expression to avoid a SQL Injection attack.
private static void VerifySortColumns(string sortColumns)
{
if (sortColumns.ToLowerInvariant().EndsWith(" desc"))
sortColumns = sortColumns.Substring(0, sortColumns.Length - 5);
string[] columnNames = sortColumns.Split(',');
foreach (string columnName in columnNames)
{
switch (columnName.Trim().ToLowerInvariant())
{
case "employeeid":
break;
case "lastname":
break;
case "firstname":
break;
case "":
break;
default:
throw new ArgumentException("SortColumns contains an invalid column name.");
break;
}
}
}
四、参数方向
默认情况下,业务对象方法的所有参数都是输入参数。如果业务对象方法包含向 ObjectDataSource 控件返回值的输出参数,必须显式指定参数和参数方向,如对数据源控件使用参数 中所述。
下面的代码示例演示一个配置为接受 Int32 类型的输出参数的 ObjectDataSource 控件。out 参数返回一个由 InsertMethod 属性所指定的方法自动生成的主键值。
<asp:ObjectDataSource
ID="EmployeeDetailsObjectDataSource"
runat="server"
TypeName="Samples.AspNet.Controls.NorthwindEmployee"
SelectMethod="GetEmployee"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
InsertMethod="InsertEmployee"
OnInserted="EmployeeDetailsObjectDataSource_OnInserted" >
<SelectParameters>
<asp:Parameter Name="EmployeeID" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="NewEmployeeID" Direction="Output"
Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:ObjectDataSource>
下面的代码示例演示以输出参数的形式返回主键值的 Insert 业务对象方法。
[DataObjectMethod(DataObjectMethodType.Insert)]
public static bool InsertEmployee(out int NewEmployeeID, string FirstName, string LastName,
string Address, string City, string Region, string PostalCode)
{
if (String.IsNullOrEmpty(FirstName))
throw new ArgumentException("FirstName cannot be null or an empty string.");