http://www.cnblogs.com/dflying/archive/2007/06/15/784053.html
本文来自《ASP.NET AJAX程序设计 第II卷:客户端Microsoft AJAX Library相关》的第三章《异步调用Web Service和页面中的类方法》,请同时参考本章的其他文章。
3.7.6 DataTable和DataSet
DataTable和DataSet是ADO.NET中的重要概念,这两个对象均非常复杂,其中包含了大量的复杂类型和循环引用。为了能够在 ASP.NET AJAX异步通讯层中传递这两种类型的数据,微软公司在ASP.NET AJAX Futures CTP版本中给出了自定义的DataTable和DataSet转换方案——即借助于ASP.NET AJAX强大的可扩展性,通过自定义JavaScriptConverter实现DataTable和DataSet类型的客户端/服务器端自动转换。
参考:在某些情况下,我们也需要通过编写自定义的JavaScriptConverter来为实际项目中遇到的某些复杂类型给出自定义的转换方案。关于JavaScriptConverter组件的基本知识,请参考第2章;关于自定义JavaScriptConverter的编写方法,将在第III 卷中介绍。
若想在ASP.NET AJAX异步通讯层中传递DataTable和DataSet这两种类型的数据,首先我们应该确保安装了ASP.NET AJAX的Futures CTP部分(关于对ASP.NET AJAX的Futures CTP部分的介绍以及安装方法,请参考第I卷),并在Web站点中添加了对Microsoft.Web.Preview.dll程序集的引用(将该程序集拷贝到Web站点的/bin文件夹下),如图3-31所示。
图3-31在Web站点中添加对Microsoft.Web.Preview.dll程序集的引用
随后让我们在web.config文件中启用ASP.NET AJAX Futures CTP中自带的DataTable和DataSet相关JavaScriptConverter组件。将如下代码添加至
<jsonSerialization>
<converters>
<add name="DataSetConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataSetConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="DataRowConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataRowConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="DataTableConverter" type="Microsoft.Web.Preview.Script.Serialization.Converters.DataTableConverter, Microsoft.Web.Preview, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
converters>
jsonSerialization>
进行上述配置之后,我们即可ASP.NET AJAX异步通讯层中传递DataTable和DataSet了,让我们通过一个实例程序说明具体的使用方法。
在本示例程序,我们将通过ASP.NET AJAX异步通讯层从服务器端Web Service方法中取得一个DataTable,并将其中的数据显示为页面中的一个HTML
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class DataService : System.Web.Services.WebService
{
[WebMethod]
public DataTable GetDataTable(string tableName)
{
// 设定DataTable的名称
DataTable table = new DataTable(tableName);
// 为该DataTable添加两列
table.Columns.Add(new DataColumn("Id", typeof(int)));
table.Columns.Add(new DataColumn("Name", typeof(string)));
// 添加5行
for (int i = 0; i < 5; ++i)
{
DataRow newRow = table.NewRow();
newRow["Id"] = i;
newRow["Name"] = string.Format("name {0}", i);
table.Rows.Add(newRow);
}
return table;
}
}
然后再客户端ASP.NET页面中添加ScriptManager控件,并引入该Web Service:
<asp:ScriptManager ID="sm" runat="server">
<Services>
<asp:ServiceReference Path="Services/DataService.asmx" />
Services>
asp:ScriptManager>
来到页面的UI部分:添加一个用来出发对服务器端Web Service方法的异步调用的按钮和一个用来显示由服务器端返回值构造出的HTML
<input id="btnGetDataTable" type="button" value="Get DataTable"
onclick="return btnGetDataTable_onclick()" />
<div id="result">
div>
btnGetDataTable按钮的click事件的处理函数定义如下:
function btnGetDataTable_onclick() {
DataService.GetDataTable("My Table", onSucceeded);
}
此时,如果一切顺利的话,在回调函数onSucceeded()中我们已经可以看到服务器端返回的DataTable的基本结构了。比如下面的代码就使用Sys.Debug.traceDump()方法(关于Sys.Debug.traceDump()方法,请参考第1章中的介绍)查看了 result对象的详细结构:
function onSucceeded(result) {
Sys.Debug.traceDump(result);
}
在Visual Studio的“Output”窗口中,我们即可看到该客户端DataTable的完整结构以及其中所包含的数据,如图3-32所示。
图3-32 客户端DataTable的完整结构以及其中所包含的数据
当然,在Visual Studio的调试器中,我们也可以直接查看该DataTable的结构和数据,如图3-33所示。
图3-33 服务器端DataTable类型在客户端的结构
从图3-32和图3-33可以看到,ASP.NET AJAX异步通讯层为服务器端DataTable生成的客户端JavaScript相应类型还是比较简单的,很多原始DataTable中的数据之间的关系和约束均没有保留下来。不过在一般的开发场景中,这些信息已经足够满足我们的使用需求了——毕竟,DataTable中的所有“数据”都丝毫不差地保留了下来。
参考:ASP.NET AJAX在Futures CTP版本中提供了更为完备的客户端DataTable类型,其完全限定名为Sys.Preview.Data.DataTable。有关该类型的详细介绍,请参考本书8.2.2节。
接下来让我们回到该示例程序的编写中来,完成回调函数onSucceeded(),将该客户端DataTable中的数据以HTML
function onSucceeded(result) {
// 测试
//Sys.Debug.traceDump(result);
//debugger;
// 得到两列的名称
var idColName = result.columns[0].name;
var nameColName = result.columns[1].name;
// 得到DataTable中的行集合
var rows = result.rows;
// 创建表格头
var builder = new Sys.StringBuilder("");
");builder.append(String.format("
", {0} {1} idColName,nameColName));// 创建表格内容
for (var rowIndex = 0; rowIndex < rows.length; ++ rowIndex) {builder.append(String.format("
", {0} {1} rows[rowIndex][idColName],rows[rowIndex][nameColName]));}builder.append("
// 显示表格
$get("result").innerHTML = builder.toString();
}
至此,我们已经完成了本示例程序的编写。运行该程序并点击“Get DataTable”按钮,将看到如图3-34所示的界面。
图3-34 从服务器端取得DataTable对象并显示在页面中
若是想得到DataSet对象,那么ASP.NET AJAX异步通讯层也有着不错的支持。在上面的DataService Web Service类中再添加如下一个方法:
[WebMethod]
public DataSet GetDataSet(string[] tableNames)
{
DataSet dataSet = new DataSet();
// 根据传入的DataTable名称创建各个DataTable
for (int i = 0; i < tableNames.Length; ++i)
{
dataSet.Tables.Add(GetDataTable(tableNames[i]));
}
return dataSet;
}
该方法接受一个字符串数组,并根据该数组的长度创建相应个数的DataTable,然后将这些DataTable打包到一个DataSet中返回给客户端。
在客户端,我们可以使用如下JavaScript调用该Web Service方法:
var dataTableNames = ["My Table 1", "My Table 2", "My Table 3"];
DataService.GetDataSet(dataTableNames, onSucceeded);
在onSucceeded()回调函数中,返回的客户端DataSet在Visual Studio调试器中显示出的结构如图3-35所示,可以看到该DataSet包含了3个DataTable对象。
图3-35服务器端DataSet类型在客户端的结构
虽然这个客户端版本的DataSet仍旧比较简单,但一般来讲,这样的数据结构已经足够我们使用了。