这篇文章将建立一列包含CheckBox控件的DataGrid这个控件允许用户对明细浏览进行多列选择如果没有恢复对于动态SQL获得该功能的一种方法那么必须使用IN操作
在文章的结尾我们写了一个SQL Server用户自定义函数(UDF)为了将一个字符串分解成带分隔符的子字符串在这篇文章中我们能看到这样一个UDF如何派得上用场我们将建立一个web表单在此用户可以通过选择checkbox控件而选择一些在DataGrid中的记录对这些被检查的记录的明细将会出现在表单中的另一个DataGrid中这个表单像来如图所示
在下面显示了我们用来建立表单的ASPX注意如何使用TemplateColumn和Checkbox控件增加DataGrid列我们也使用DataGrid的DataKeyField属性来告诉对象在数据库记录的哪一个字段将会包含第一行的关键字标示符
<form id=Form method=post runat=server>
<asp:DataGrid id=DataGrid runat=server
AutoGenerateColumns=False DataKeyField=EmployeeID>
<Columns>
<asp:TemplateColumn>
<ItemTemplate>
<asp:CheckBox runat=server ID=EmployeeCheckBox />
</ItemTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn>
<ItemTemplate>
<%# DataBinderEval(ContainerDataItem LastName) %>
<%# DataBinderEval(ContainerDataItem FirstName) %>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
<hr>
<asp:Button id=Orders runat=server Text=View Orders></asp:Button>
<hr>
<asp:DataGrid ID=DataGrid Runat=server AutoGenerateColumns=True />
</form>
当表单加载初始化时需要组装顶端的DataGrid代码使用Enterprise Library来存取SQL Sever Northwind例子数据库并且执行SELECT EmployeeIDFirstNameLastName FROM Employees这一语句加载事件的代码如下
private void Page_Load(object sender SystemEventArgs e)
{
if(!PageIsPostBack)
{
Database db = DatabaseFactoryCreateDatabase();
DBCommandWrapper dbCommandWrapper;
using(dbCommandWrapper = dbGetSqlStringCommandWrapper(SELECT_EMPLOYEES))
{
using (IDataReader dataReader = dbExecuteReader(dbCommandWrapper))
{
DataGridDataSource = dataReader;
DataGridDataBind();
}
}
}
}
当用户单击Orders按钮时我们想显示与数据库中的那些与Employees相配并与Orders数据相关的第二个数据表格这样做的一种方法是建立动态的SQL并且使用所有EmployeeIDs所需的WHERE语句的OR条件
第二个方法是使用WHERE语句的IN操作IN操作将会一列表达式进行比较例如下列语句返回employee中IDS 和之间的信息
SELECT EmployeeID FirstName LastName FROM Employees WHERE EmployeeID IN ( )
在观念上说我愿意使用一个单一字符串参数来查询所传递的IDs然而也许作为一个单字符串不能对IN操作使用一个单一字符串参数如果那样SQL语句会这样WHERE Employee IN ()并且数据库因为EmployeeID属于类型int—不属于varchar类型而返回一个错误消息
不过我们使用文章中构造的split函数将字符串分离成不同的值向split函数传递字符串并且我们会得到与值和相对应的两条记录选择employees并且计算它们的定单总数的SQL查询将会如下
SELECT count(*) AS Orders EFirstName ELastName
FROM Orders O
INNER JOIN Employees E ON OEmployeeID = EEmployeeID
WHERE EEmployeeID IN(SELECT Value FROM fn_Split(@employeeIDs ))
GROUP BY FirstName LastName
ORDER BY count(*) DESC
使用以上查询所需要的是必须建立和传递@employeeIDs参数这个参数将是用逗号隔开的IDs列表为了建立该字符串为了弄明白行是否被用户选择我们需要使用一个循环这一循环以行数循环次数并且检查每一个checkbox控件如果用户选择了行通过从表的DataKeys属性中(它被建立在ASPX文件中来指向EmployeeID字段)提取检验人将关键字保存在employee中
private string GetCheckedEmployeeIDs()
{
String delimiter = StringEmpty;
StringBuilder employeeIDs = new StringBuilder();
for(int i = ; i < DataGridItemsCount; i++)
{
CheckBox checkbox;
checkbox = DataGridItems[i]FindControl(EmployeeCheckBox) as CheckBox;
if(checkbox != null && checkboxChecked == true)
{
employeeIDsAppend(delimiter + DataGridDataKeys[i]ToString()) ;
delimiter = ;
}
}
return employeeIDsToString();
}
以上方法返回一个字符串像对Orders按钮单击事件处理器将涉及这样一个方法将信息传递至SQL以得到employees和orders的列表并且将其结果绑定在第二个DataGrid对象中
private void Orders_Click(object sender SystemEventArgs e)
{
string employeeIDs = GetCheckedEmployeeIDs();
Database db = DatabaseFactoryCreateDatabase();
DBCommandWrapper dbCommandWrapper;
using(dbCommandWrapper = dbGetSqlStringCommandWrapper(SELECT_ORDERS))
{
dbCommandWrapperAddInParameter(@employeeIDs DbTypeString employeeIDs);
using (IDataReader dataReader = dbExecuteReader(dbCommandWrapper))
{
DataGridDataSource = dataReader;
DataGridDataBind();
}
}
}