如何返回一個 DataTable 到用戶端 JavaScript

來源:互聯網
上載者:User

當在 WebService 中直接返回 DataTable 時,會出現循環參考的異常,

何為循環參考?循環參考就是在引用上,

A 引用了 B,而 B 又引用了 A,這就是一個典型的循環參考,

當有循環參考時,在進行 JSON 序列化時會報出出現循環參考的異常,

例如

我在 WebService 中返回的是一個 DataTable 類型,

DataTable 算是一個極其複雜的物件類型了,

這個類型在進行 JSON 序列化時,便會產生一個循環參考,

在序列化其中的 System.Reflection.Module 對象時會發生循環參考,

從而會導致 JSON 序列化失敗,導致整個的非同步呼叫 WebService 失敗,

看一下這個失敗的例子吧,

首先看 .asmx

[WebMethod]
[System.Web.Script.Services.ScriptMethod]
public DataTable GetDataTable()
{
    DataTable myTable = new DataTable();

    DataRow myRow;
    myTable.Columns.Add("ID", typeof(string));
    myTable.Columns.Add("Name", typeof(string));
    myTable.Columns.Add("Sex", typeof(string));
    myTable.Columns.Add("FatherName", typeof(string));
    myTable.Columns.Add("Address", typeof(string));

    string conStr = WebConfigurationManager.
                    ConnectionStrings["Demo"].ConnectionString;
    string sqlStr = "SELECT 社會安全號碼碼,學生姓名,性別,家長姓名,家庭地址 FROM 學生";

    using (SqlConnection sqlCon = new SqlConnection(conStr))
    {
        sqlCon.Open();
        using (SqlCommand sqlCom = sqlCon.CreateCommand())
        {
            sqlCom.CommandText = sqlStr;
            using (SqlDataReader sqlDr = sqlCom.ExecuteReader())
            {
                while (sqlDr.Read())
                {
                    myRow = myTable.NewRow();
                    myRow["ID"] = sqlDr.GetSqlString(0).Value;
                    myRow["Name"] = sqlDr.GetSqlString(1).Value;
                    myRow["Sex"] = sqlDr.GetBoolean(2).ToString();
                    myRow["FatherName"] = sqlDr.GetSqlString(3).Value;
                    myRow["Address"] = sqlDr.GetSqlString(4).Value;
                    myTable.Rows.Add(myRow);

                }
            }
        }
    }
    return myTable;
}

顯而易見,上面這個 WebService 返回的是一個 DataTable 對象

再看一下用戶端 JavaScript 代碼

function PageLoad() {
    深入淺出_ASP.NET_AJAX.Demo__10__Use.
             set_timeout(2000);
    深入淺出_ASP.NET_AJAX.Demo__10__Use.
             set_defaultFailedCallback(OnFailedCallback);
    深入淺出_ASP.NET_AJAX.Demo__10__Use.
             set_defaultSucceededCallback(OnSucceededCallback);
}

function GetDataTable_onclick() {
    深入淺出_ASP.NET_AJAX.Demo__10__Use.GetDataTable();
}

function OnFailedCallback(error, userContext, methodName) {
    var msg = "";
    if (methodName == "GetDataTable") {
        msg += "\nGetDataTable 在非同步執行期間發生下列錯誤";
    }

    msg += "\n 異常資訊:    " + error.get_message();
    msg += "\n 異常類型:    " + error.get_exceptionType();
    msg += "\n 狀態代碼  :    " + error.get_statusCode();
    msg += "\n 堆棧資訊:    " + error.get_stackTrace();

    alert(msg);
}

function OnSucceededCallback(result, userContext, methodName) {
}
執行中由於 DataTable 在序列化時會發生循環參考,所以很明顯,會失敗

單擊這個 Button 後的結果為

以上是在從 WebService 中直接返回 DataTable 時出現的異常,

那麼該如何解決這個問題呢,使得能夠從服務端順利的返回 DataTable 中的資料呢?

事實上,應該明確以下幾點,

在服務端與用戶端進行傳遞資料的格式是 JSON (JavaScript Object Notation),

這個格式簡單輕便,

最常用的以一般的字串類型, List<T> 集合類型以及

字典Dictionary<string ,T>類型進行資料的傳遞和轉換

其中較為特殊的是 Dictionary<string ,T>,

其中的第一個類型必須是 string ,否則在用戶端將無法識別,

而 DataTable 或者 DataSet 這些複雜資料類型已經遠遠超出了上面的三種類型的範圍,

所以無法進行正常的 JSON 序列化,

那麼如何才能正常的把 DataTable 中的資料正確傳遞給 JavaScript 呢?

其中有兩種方法對這種情況可以解決,

第一種是使用 JavaScriptConverter 來實現,

第二種則是自訂資料類型,

          把 DataTable 這些複雜資料類型先轉換為上面的三種資料類型再傳遞。

本次主要講解一下的是第二種方法,

第一種方法相對來說更為複雜,您必須定義自己的 Converter 來實現,

同時將這個 Converter 在 Web.Config 中實現註冊,

並且必須自行控制解除或者設定循環參考,相對來說比較繁瑣,

但是第二種方式則比較簡單,

因為我是採用在服務端將 DataTable 先轉化為自訂資料類型,

然後再返回我的自訂資料類型,從而間接的實現了返回 DataTable ,

而第一種使用 JavaScriptConverter 則是直接返回的 DataTable 。

改進如下(使得上個失敗的例子可以成功返回 DataTable 中的資料)

通過添加一個類來實現將 DataTable 轉換為 List<T> 或者 Dictionary<string ,T>來返回,

類的代碼如下

public class Demo__10__Use__Converter
{
    private DataTable myTable;

    //在建構函式中傳入一個 DataTable
    public Demo__10__Use__Converter(DataTable myTable)
    {
        this.myTable = myTable;
    }

    //注意返回的類型,將 DataTable 轉換後返回的類型是 List<T>
    //此處定義了多級的 List
    //第一級 List 來儲存 DataTable 中的每一行,也就是儲存第二級 List
    //而第二級 List 則是用來儲存 DataTable 中每一行中的資料,即 Dictionary
    //而 Dictionary 則是用來儲存每一個儲存格的數值
    public List<List<Dictionary<string, string>>> Converter()
    {
        //第一級 List
        List<List<Dictionary<string, string>>> firstList =
                   new List<List<Dictionary<string, string>>>();
        //遍曆 DataTable 的每一行
        for (int i = 0; i < this.myTable.Rows.Count; i++)
        {
            //第二級 List
            List<Dictionary<string, string>> secondList =
                   new List<Dictionary<string, string>>();
            //遍曆 DataTable 的每一列
            for (int j = 0; j < this.myTable.Columns.Count; j++)
            {                   
                //擷取這個儲存格所在列的列名
                string columnName = this.myTable.Columns[j].ColumnName;
                Dictionary<string, string> myDictionary =
                      new Dictionary<string, string>();
                //將這個儲存格的數值儲存在字典中
                myDictionary[columnName] = this.myTable.Rows[i][j].ToString();
                secondList.Add(myDictionary);
            }
            firstList.Add(secondList);
        }
        return firstList;
    }
}

然後再在 WebService 中更改一點點就 OK 了

接下來就是要在 JavaScript 中解析,

傳遞過來的 List<List<Dictionary<string,string>>>類型並且輸出了

再看一下結果吧

該部分的代碼需要仔細斟酌,慢慢理解

以上就是在服務端傳遞 DataTable 到用戶端 JavaScript 的整個範例,

大家可以慢慢研究。

                                             2010—1—27

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.