C#开发训练营

第17课:数据库操作基础——tDataHelpler类

开发工作中,可以将DataTable对象作为数据的中间格式,并转换为各种所需的格式,如HTML表格、HTML列表、JSONArray和JSONObject文本等格式;本课将封装tDataHelper类,其中包含了相关的转换工作。

DataTable转换HTML表元素

首先来看tDataHelper.GetTableHtml()方法的定义,如下面的代码(/app_code/data/base/tDataHelper.cs)。

C#
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;

public static class tDataHelper
{
    // 在服务器端生成行操作,opt中的{0}替换为pkName中的行数据
    public static string GetTableHtml(DataTable data,
        string pkName, bool showPkColumn, string clientId, string opt)
    {
        if (data == null || data.Columns.Count<=0 || 
            data.Rows.Count <= 0) return "";
        // 处理主键
        if (data.Columns.Contains(pkName)) 
            data.Columns[pkName].SetOrdinal(0);
        else 
            return "";
        int colStartIndex = showPkColumn ? 0 : 1;
        //
        StringBuilder sb = new StringBuilder(3000);
        sb.AppendFormat("<table class='table_normal' id='{0}'>", clientId);
        // 标题行
        sb.Append("<tr rownum='0'>");
        for (int col = colStartIndex; col < data.Columns.Count; col++)
            sb.AppendFormat("<th>{0}</th>", data.Columns[col].ColumnName);
        sb.Append("<th>操作</th></tr>");
        // 数据行
        bool alternationRow = false;
        for (int row = 0; row < data.Rows.Count; row++)
        {
            sb.AppendFormat("<tr {0} rownum='{1}' rowdata='{2}'>",
                (alternationRow ? "class='alternation_row'" : ""),
                row + 1, data.Rows[row][pkName]);
            alternationRow = !alternationRow;
            //
            for (int col = colStartIndex; col < data.Columns.Count; col++)
            {
                sb.AppendFormat("<td>{0}</td>", data.Rows[row][col]);
            }
            // 行操作
            sb.AppendFormat("<td>{0}</td>", 
                string.Format(opt, data.Rows[row][pkName]));
            //
            sb.Append("</tr>");
        }
        //
        sb.Append("</table>");
        //
        return sb.ToString();
    }
    // 其它代码...
}

tDataHelper.GetTableHtml()方法需要五个参数,分别是:

  • data,定义为DataTable对象,指定需要转换为HTML表元素(table)的数据。
  • pkName,指定DataTable对象中的主键列名。
  • showPkColumn,在HTML的表元素中是否显示主键列。
  • clientId,设置table元素的id属性值。
  • opt,设置每行的操作,其中的{0}会替换为行主键数据。

下面的代码演示了tDataHelper.GetTableHtml()方法的基本应用。

C#
DataTable data =
    tApp.Db.GetJet().GetTable("select * from user_main");
tWeb.Write(tDataHelper.GetTableHtml(data, "userid", true, "gv1"));

代码中读取了cdb_demo数据库中user_main表的全部内容,生成的HTML代码如下(省去userpwd字段数据)。

HTML
<table class='table_normal' id='gv1'>
<tr rownum='0'>
<th>userid</th><th>username</th><th>userpwd</th><th>email</th><th>locked</th><th>操作</th>
</tr>
<tr  rownum='1' rowdata='1'>
<td>1</td><td>user01</td><td>...</td><td>user01@aaa.bbb</td><td>0</td>
<td><a href='Edit.aspx?id=1'>编辑</a></td>
</tr>
<tr class='alternation_row' rownum='2' rowdata='2'>
<td>2</td><td>user02</td><td>...</td><td>user02@aaa.bbb</td><td>1</td>
<td><a href='Edit.aspx?id=2'>编辑</a></td>
</tr>
<tr  rownum='3' rowdata='3'>
<td>3</td><td>user03</td><td>...</td><td>user03@xxx.yyy</td><td>0</td>
<td><a href='Edit.aspx?id=3'>编辑</a></td>
</tr>
<tr class='alternation_row' rownum='4' rowdata='4'>
<td>4</td><td>user04</td><td>...</td><td>user04@xxx.yyy</td><td>0</td>
<td><a href='Edit.aspx?id=4'>编辑</a></td>
</tr>
<tr  rownum='5' rowdata='5'>
<td>5</td><td>user05</td><td>...</td><td>user05@xxx.yyy</td><td>0</td>
<td><a href='Edit.aspx?id=5'>编辑</a></td>
</tr>
</table>

可以看到,table元素中设置了class属性为table_normal,id为tDataHelper.GetTableHtml()方法的clientId属性指定。

table元素的第一行是列标题行,其中使用了th元素显示列名,并在最后一列显示“操作”。此外,标题行的tr元素中还设置了rownum属性为0。

数据行的tr元素中,使用rownum属性设置了从1开始的行号,rowdata属性设置每行的主键字段数据。每隔一行还会在tr元素中设置class属性为alternation_row。

图1是使用了一些CSS样式后的显示效果,其中,间隔行使用了浅黄色的背景。

图1

开发中,还可以根据需要创建GetTableHtml()方法的重载版本,后续课程中还会有相关讨论。

DataTable转JSON格式

数据交换过程中,JSON是一种简单易用的格式,在tDataHelper类中封装了GetJson()方法,用于将DataTable对象数据转换为JSON数据的文本格式,方法定义如下。

C#
// 转换为JSON文本
public static string GetJson(DataTable data)
{
    if (data == null || data.Columns.Count == 0 || 
        data.Rows.Count == 0) return "";
    //
    StringBuilder sb = new StringBuilder("[", data.Rows.Count * 100);
    // 数据行
    for (int row = 0; row < data.Rows.Count; row++)
    {
        sb.Append("{");
        sb.AppendFormat("\"{0}\":\"{1}\"",
            data.Columns[0].ColumnName, data.Rows[row][0]);
        for(int col = 1; col < data.Columns.Count; col++)
        {
            sb.AppendFormat(",\"{0}\":\"{1}\"",
                data.Columns[col].ColumnName, data.Rows[row][col]);
        }
        sb.Append("},");
    }
    // 去掉最后一个逗号
    sb.Remove(sb.Length - 1, 1);
    //
    sb.Append("]");
    return sb.ToString();
}

tDataHelper.GetJson()方法的参数包括只需要指定需要转换的DataTable对象。方法中,会将DataTable对象中的数据转换为如下格式的JSON文本。

JSON
[{...},{...},{...}...]

生成的文本中,整体数据定义为JSONArray格式,每行记录定义为一个JSONObject格式,即Dictionary或Map对象,其中的每个数据定义为“键/值”格式。

下面的代码会将用户表(user_main)中的数据转换为JSON文本格式。

C#
using System;
using System.Data;

public partial class Test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable data =
            tApp.Db.GetJet().GetTable("select * from user_main");
        tWeb.Write(tDataHelper.GetJson(data));
    }
}

代码生成的内容如下。

JSON
[
{"userid":"1","username":"user01",
"userpwd":"...","email":"user01@aaa.bbb","locked":"0"},
{"userid":"2","username":"user02",
"userpwd":"...","email":"user02@aaa.bbb","locked":"1"},
{"userid":"3","username":"user03",
"userpwd":"...","email":"user03@xxx.yyy","locked":"0"},
{"userid":"4","username":"user04",
"userpwd":"...","email":"user04@xxx.yyy","locked":"0"},
{"userid":"5","username":"user05",
"userpwd":"...","email":"user05@xxx.yyy","locked":"0"}
]

在客户端的JavaScript代码中,可以使用JSON.parse()方法将这些文本内容很方便地转换为JavaScript数组。

数组和tPairList转JSON

JSON是一种很灵活的格式,在数据交换过程中可以根据需要灵活应用,下面的代码,我们会在tDataHelper类中添加一些方法,分别将Array和tPairList数据转换为相应的JSON格式文本。

C#
// Array转JSON数组
public static string GetJson(Array arr)
{
    if (arr == null) return "";
    StringBuilder sb = new StringBuilder("[", arr.Length * 10);
    sb.AppendFormat("\"{0}\"", arr.GetValue(0));
    for (int i = 1; i < arr.Length; i++)
        sb.AppendFormat(",\"{0}\"", arr.GetValue(i));
    sb.Append("]");
    return sb.ToString();
}

// tPairList转JSON对象
public static string GetJson(tPairList lst)
{
    if (lst == null) return "";
    StringBuilder sb = new StringBuilder("{", lst.Count * 20);
    sb.AppendFormat("\"{0}\":\"{1}\"",lst[0].Name,lst[0].Value);
    for (int i = 1; i < lst.Count; i++)
        sb.AppendFormat(",\"{0}\":\"{1}\"", lst[i].Name, lst[i].Value);
    sb.Append("}");
    return sb.ToString();
}

代码中,GetJson(Array)方法会将C#数组中的数据转换为JSONArray格式的文本内容,在JavaScript代码中可以通过JSON.parse()方法将文本内容转换为JavaScript数组。GetJson(tPairList)方法可以将封装的tPairList对象中的数据转换为JSONObject格式的文本内容,在JavaScript代码中同样可以使用JSON.parse()方法转换为JavaScript数组,并使用“键/值”格式访问数据。

更详细的JSON和JavaScript应用可以参考《网站全栈开发指南:HTML+CSS+JavaScript+PHP》或《网站全栈开发指南:HTML+CSS+JavaScript+ASP.NET》。

DataTable转HTML列表

很多情况下,网页中会使用列表显示数据,我们可以在tDataHelper类中封装一些方法,用于将DataTable对象中的数据转换为包含链接的HTML列表内容,如下面的代码。

C#
public static string GetListHtml(DataTable data,string clientId,
    string pkName,string textFieldName,string hrefTemplate,string target)
{
    if (data == null || data.Rows.Count <= 0) return "";
    if (data.Columns.Contains(pkName) == false) return "";
    StringBuilder sb = new StringBuilder(1500);
    sb.AppendFormat("<ul id='{0}' class='res_list'>", clientId);
    for (int i = 0; i < data.Rows.Count; i++)
    {
        sb.AppendFormat("<li rownum='{0}'><a href='{1}' target='{2}'>{3}</a></li>",
            i+1,
            string.Format(hrefTemplate,data.Rows[i][pkName]),
            target,
            data.Rows[i][textFieldName]);
    }
    sb.Append("</ul>");
    return sb.ToString();
}

代码中,GetListHtml()方法定义的参数包括:

  • data,使用DataTable对象指定数据源。
  • clientId,列表元素的id属性名。
  • pkName,DataTable对象中主键字段的名称。
  • textFieldName,在列表项(li元素)中显示的文本内容字段。
  • hrefTemplate,列表项中a元素的href属性值模板,其中的{0}会使用每行的主键数据替换。
  • target,a元素的target属性,如_blank、_self。

下面的代码演示了tDataHelper.GetListHtml()方法的应用。

C#
using System;
using System.Data;

public partial class Test : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        DataTable data =
            tApp.Db.GetJet().GetTable("select * from user_main");
        tWeb.Write(tDataHelper.GetListHtml(data,"lst1","username","username",
            "Edit.aspx?user={0}","_blank"));
    }
}

代码中,会将user_main表中数据生成为操作列表,以username字段作为主键和显示内容;链接页面为Edit.aspx,并使用user参数指定用户名,生成的HTML内容如下。

HTML
<ul id='lst1' class='res_list'>
<li rownum='1'><a href='Edit.aspx?user=user01' target='_blank'>user01</a></li>
<li rownum='2'><a href='Edit.aspx?user=user02' target='_blank'>user02</a></li>
<li rownum='3'><a href='Edit.aspx?user=user03' target='_blank'>user03</a></li>
<li rownum='4'><a href='Edit.aspx?user=user04' target='_blank'>user04</a></li>
<li rownum='5'><a href='Edit.aspx?user=user05' target='_blank'>user05</a></li>
</ul>

这里,在li元素中还添加了rownum属性用于指行列表项的行号,可以配合listview.js中的代码实现分页浏览功能,后续内容中会有详细讨论。