65.9K
CodeProject 正在变化。 阅读更多。
Home

Auto-SQL DataGrid 组件。第一部分:非编辑版本

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (3投票s)

2005 年 8 月 9 日

5分钟阅读

viewsIcon

27630

downloadIcon

664

ASQLDataGrid 是处理 RDBMS(关系数据库管理系统)应用程序时的一个有用组件。它能够根据其属性自动构建和执行 SQL 语句。

什么是 Auto SQL DataGrid?

Auto SQL DataGrid 能够仅使用 DataGrid 及其列的属性信息,自动生成用于填充、插入、更新和删除数据库中数据的 SQL 语句。在最佳情况下,您只需将 DataGrid 的 ID 命名为数据库表名,并将每列的 DataField 设置为对应的数据库列名,ASQLDataGrid 就会为您完成所有神奇的操作。它还提供了一个简单直观的编程接口,用于改变默认行为,以处理更复杂的场景,例如当您需要在 Select 语句中连接两个或多个数据库表时。在本系列的第一篇文章中,我将介绍 ASQLDataGrid 的非编辑版本,而第二篇文章将完成该类,添加插入、更新和删除功能。您应该熟悉关系数据库管理系统 (RDBMS) 的基础知识和 SQL 语句的语法,才能使用 ASQLDataGrid 组件。

CmdButtonForm 和 CmdButton 类

您可以在我之前的文章 这里 查看有关如何使用 CmdButtonForm 类的详细信息。简而言之,它提供了一个类库级别的机制,通过使用隐藏的标签来处理窗体上的(多个)提交按钮。您应该像这样继承自己的 WebForm:
public class WebForm1 :NTM.Controls.CmdButtonForm
CmdButton 类是 CmdButtonForm 的配套类。它有两个公共属性:Cmd,用于指定要执行的命令(如 Populate、Save 等);以及 Param,用于参数字符串(例如目标 DataGrid 的 ID)。在示例项目中,我像这样向 Web 窗体添加了 Populate 按钮:
<ntm:CmdButton id="btPopEmployees" runat="server" Cmd="DG_POP" Param="DG_Employees" Text="Populate" Width="73"></ntm:CmdButton>

ASQLDataGridCmdExecutor 类

ASQLDataGridASQLCmdExecutor 属性指定了用于处理命令的对象,该对象应该从 ASQLDataGridCmdExecutor 类或其继承类实例化。如果您没有为该属性分配任何值,ASQLDataGrid 类将创建一个默认的 ASQLDataGridCmdExecutor 对象,并让它处理(标准)命令。
protected override void OnLoad(EventArgs e)
{
...
            if (this._ASQLCmdExecutor == null)
            {
                //Create and use a default command executor
                this._ASQLCmdExecutor = new ASQLDataGridCmdExecutor();
            }
            _ASQLCmdExecutor.ExecuteCmd(this, Command, CommandParam);
...
}
除了 DG_POP(从数据库填充数据)等标准命令外,您还可以定义任何命令并编写自己的命令执行程序来处理它。例如,您可能想要一个“全部删除”按钮。首先,您应该在 Web 窗体中添加命令按钮:
<ntm:cmdbutton id="btDelAllEmployees" runat="server" Cmd="DG_DELALL" Param="DG_Employees" Text="Delete All" Width="73"></ntm:cmdbutton>
如下面的代码所示,您可以继承自己的命令执行程序类,从 ASQLDataGridCmdExecutor 类派生:
public class MyCmdExecutor : ASQLDataGridCmdExecutor
{
    public override void ExecuteCmd(ASQLDataGrid dg, string Cmd, string CmdParams)
    {
        if (Cmd.Equals("DG_DELALL"))
        {                           
            //Write you own code to here
            ...
        }
        else
            base. ExecuteCmd (dg, Cmd, CmdParams);
    }
}
现在,在 WebForm 中,您可以像这样将新开发的命令执行程序分配给 DataGrid:
private void Page_Load(object sender, System.EventArgs e)
{
    ...
    DG_Employees.ASQLCmdExecutor = new MyCmdExecutor ();                                              
    ...
}

ASQLDataGridStatBuilder 类

组件的核心来了——SQL 语句(自动)构建器类。与命令执行程序一样,如果您不为 ASQLDataGridASQLBuilder 属性指定任何值,它将创建一个默认的 ASQLDataGridStatBuilder 实例并使用它来构造 SQL 语句。让我们看看这个默认的 ASQLDataGridStatBuilder 对象的功能。以下是它的 BuildSelect 方法(返回整个 Select 语句)的样子:
public virtual string BuildSelect(ASQLDataGrid dg)
{
    return  "select " + SEL_BuildListOfColumns(dg) + " from " + SEL_BuildFromClause(dg) + SEL_BuildWhereClause(dg)
                + SEL_BuildGroupByClause(dg) + SEL_BuildHavingClause(dg) + SEL_BuildOrderByClause(dg);
}

语句构建器将 select 语句分解为更小的子句:列列表、FROM 和 WHERE 条件、GROUP BY、HAVING 和 ORDER BY 子句。默认情况下,WHERE、GROUP BY、HAVING 和 ORDER BY 子句返回空字符串。FROM 子句从 DataGrid 的 ID 中提取,方法是取其第一个下划线字符之后的所有字符(如果存在)。这意味着当处理名为 Employees 的数据库表时,我们应该将 ASQLDataGrid 的 ID 分配为例如 DG_Employees。SEL_BuildListOfColumns 方法通过逗号分隔每个列的 GetDBColumnName 方法的返回值来连接所有字符串,而 GetDBColumnName 又返回 BoundColumn/HyperLinkColumnDataFieldDataTextField。如果您使用 TemplateColumns,您应该编写自己的 Statement Builder 并指定正确的 DB 列,正如我稍后将展示的那样。请注意,我遵循 MS Trans-SQL 的 select 语句(以及第二篇文章中的其他语句)的语法实现了 statement builder 类。您可能需要修改它并实现自己的 statement builder 版本以满足您的需求(例如,处理其他 RDBMS)。

示例项目使用 MS NorthWind 数据库中的 Employees 表。要获得一个显示当前员工列表的 DataGrid,您所要做的就是创建一个 ID 为 DG_Employees 的 ASQLDataGrid,并将每个 BoundColumnDataField 属性设置为相应的 DB 列名(例如,EmployeeID、TitleOfCourtesy、FirstName、LastName、BirthDate、Address 和 ReportsTo)。Statement Builder 将帮助我们构造 Select 语句,该语句将是:

select EmployeeID, TitleOfCourtesy, FirstName, LastName, BirthDate, Address, ReportsTo from Employee

如前所述,添加 Populate 命令按钮,这样我们就拥有了一个工作的 DataGrid 应用程序。非常易于使用,不是吗?现在,我们将看到如何修改此默认语句构建器以改进我们的示例应用程序。目前,ReportsTo 列包含 EmployeeID(即该员工需要汇报的对象),我们希望显示这些人的姓名而不是 ID。为此,我们必须在 select 语句中将 Employee 数据库表连接到自身。所以我们像这样从 ASQLDataGridStatBuilder 类继承自己的 Statement Builder:

    
public class ASQLBuilder1 : ASQLDataGridStatBuilder
{
    public override string  SEL_BuildFromClause(ASQLDataGrid dg)
    {
        return "Employees E1 left join Employees E2 on E1.ReportsTo = E2.EmployeeID";
    }
    public override string GetDBColumnName(TypeOfSQLStatement stat, ASQLDataGrid dg, int ColumnIndex)
    {
        if (ColumnIndex == 6)
        {
            //ReportsTo
            if (stat == TypeOfSQLStatement.Select)
            {
                return "(E2.FirstName + ' ' + E2.LastName) as ReportsTo";
            }
            else
                return base.GetDBColumnName(stat, dg, ColumnIndex);
        }
        else
        {
            if (stat == TypeOfSQLStatement.Select)
            {
                //Qualifying all the column with the (E1) table name
                string DBColName  = base.GetDBColumnName(stat, dg, ColumnIndex);
                if (DBColName.Length>0)
                    return "E1." + DBColName;
                else
                    return "";
            }
            else
                return base.GetDBColumnName(stat, dg, ColumnIndex);
        }
    } 
如您所见,我们覆盖了 Statement Builder 的 SEL_BuildFromClause 方法,现在它返回两个 Employee 表的连接。此外,我们必须使用表名限定所有列名,并通过覆盖 GetDBColumnName 方法(如下所示)来显示 ReportsTo 人员的姓名而不是 ID。现在,新开发的 Statement Builder 将帮助我们构造最终的 Select 语句:
select E1.EmployeeID,E1.TitleOfCourtesy,E1.FirstName,E1.LastName,E1.BirthDate,E1.Address,(E2.FirstName + ' ' + E2.LastName) as ReportsTo 
        from Employees E1 left join Employees E2 on E1.ReportsTo = E2.EmployeeID
实际上,通过覆盖 ASQLDataGridStatBuilder 类的适当方法,您可以获得一个 Statement Builder,它能够构建您的实际应用程序所需的非常复杂的 SQL 语句。编写自己的 Statement Builder 后,请不要忘记像之前展示的 Command Executor 那样将其分配给 DataGrid。
private void Page_Load(object sender, System.EventArgs e)
{
    ...
    DG_Employees.ASQLBuilder = new ASQLBuilder1();
    ...
}
最后的注意事项是,您甚至可以使用一个 Statement Builder 来服务于多个 ASQLDataGrid。有时这可以减少开发时间。

结论

此处介绍的 ASQLDataGrid 是处理 RDBMS 时的有用组件。它可以缩短开发时间;帮助您专注于实际的业务逻辑,而不是处理 SQL 语法。我将在第二篇文章中完成该类的自动构建插入、更新和删除语句的功能。

编程愉快!

历史

  • 2005 年 8 月 8 日 - 初始版本。
© . All rights reserved.