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

nTier 代码生成器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (3投票s)

2012年11月27日

CPOL

8分钟阅读

viewsIcon

29879

downloadIcon

2058

一个小型实用工具,用于为 n-tier 系统中的每个层生成 C# 代码。

引言

如果您是 n-tier 架构的新手,此工具将帮助您理解您正在构建的内容。如果您是 n-tier 的老手,我告诉您一些您早已知道的事情:手动构建所有基础层可能会很乏味。

如果您查看源代码,您会发现我只是使用一种蛮力方法将必需的代码写入指定的文件夹和文件。请随意改进代码并与大家分享。

背景

多层架构系统提供的强大功能和灵活性是我无法放弃的。业务系统正变得越来越复杂,用户要求友好地处理多步流程,而业务规则总在变化。我需要一个工具来减少构建这些基础层所带来的繁琐编码工作量,但我也希望能够在任何地方更改任何代码,而无需重写大部分内容。

代码

代码分为五个部分
  1. 控件行为
  2. BE 代码
  3. BLL 代码
  4. DAL 代码
  5. UI 代码

每个部分遵循相同的流程

  1. 从控件获取输入的命名空间、文件夹和类信息
  2. 分配适当的数据类型
  3. 将代码写入指定文件夹

每个项目层都以相同的方式创建。这是创建 BE 层 .^{1}代码。

StreamWriter sw = File.CreateText(txtConstants.Text.Trim() + className + ".cs");
sw.WriteLine("using System;"); 
sw.WriteLine("");
sw.WriteLine("namespace " + txtBENamespace.Text.Trim() + ".Constants");
sw.WriteLine("{");
sw.WriteLine("  public enum " + className + "Fields");
sw.WriteLine("  {");
fCount = 1;
foreach (PropertyMap field in fieldList)
{
    if (fCount > 1)
        sw.Write(", " + field.Name);
    else
        sw.Write("    " + field.Name);
    fCount++;
}
sw.WriteLine("");
sw.WriteLine("  }");
sw.WriteLine("}");
sw.Close();
sw.Dispose();

PropertyMap 类保存数据库表中每个字段的属性,以及分配给它的控件类型和控件名称。这个类的格式与 BE 层中编写的类完全相同。

使用该工具

下载已编译的实用工具,可以从此处或我的网站下载。我的网站 (http://veracitysystems.com/downloads/public) 将始终提供最新版本的代码。

在 Visual Studio 中创建一个新的空解决方案,然后为每个层创建一个空项目。

运行该工具,让它为每个层的文件夹创建代码。在解决方案资源管理器中点击“显示所有文件”按钮,并将新文件包含在您的项目中。

其次,如果您想了解它是如何工作的,请下载源代码。同样,最新版本的源代码在我的网站上。

我做了一些注释和假设,这些对于新手 n-tier 设计师来说很重要,所以如果您是经验丰富的程序员,可以忽略本节的其余部分。

该工具将创建以下层

  1. 业务实体(也称为业务对象),我将其称为 BE 层。这些非常轻量级、极其小巧且速度很快。
  2. 业务逻辑层(也称为业务规则),我将其称为 BLL 层。这些也小巧高效,您可以在此处放置自己的业务逻辑。
  3. 数据访问对象,我将其称为 DAL 层。基础层中的主力,这些类代表您的应用程序与您的数据库通信。
  4. 用户界面,我将其称为 UI。
当然还有其他层,其中有两个我一直都在使用。它们是表示实体/对象(PE)和表示逻辑(PL)。该工具目前不处理后两个,但它创建的内容足以让您很好地享受到 n-tier 的优势。

以下假设和结果适用

  1. 该工具仅生成 C# 代码。没有 VB 版本。
  2. 该工具假定每个数据库表都在单个字段上设置了主键(PK)。
  3. 该工具假定数据库表名是单数形式。(复数也可以,但您需要在编译前对手动修改 DAL 代码做一点小改动)。
  4. 该工具只处理最常见的数据类型。如果您正在使用 SQL 2012 中引入的任何新数据类型(空间数据等),那么您需要自己将它们添加到源代码中(或者等到我需要它们的时候)。
  5. 该工具将生成代码,以确保您再也不会遭受 SQL 注入攻击。所有发送到数据库的命令都已参数化。
  6. 所有创建的适当方法都可以在您的 Intellisense 列表中找到。
  7. 所有代码都符合 Microsoft 的编码约定。(参见 此处此处)。

BE 代码

该工具创建的第一个项目是业务实体层。

Enums

该工具将创建一组枚举,您可以使用它们来引用字段,并且重要的是,将它们作为参数传递。

AdoDotNetDataProvider

AdoDotNetDataProvider 类处理通用数据提供程序。

  • SQL
  • OLE
  • ODBC

当然,您可以添加自己的(Oracle 等)。

BLL 代码

BLL 类模仿其 DAL 同类项,也许这就是您需要做的全部。但是,如果您有在多个地方使用的业务逻辑代码,那么这个层就是存放它的地方。

DAL 代码

DAL 不处理任何存储过程。如果您仔细想想,SP 包含业务逻辑,而业务逻辑属于 BLL。我知道有很多理由可以证明 SP 是好的,我不想再争论“正确”的编码方式; suffice to say,此工具不支持 SP。

这是 SelectByID() 方法。它返回该类类型的单个对象。

swDAL.WriteLine("       public static BE SelectById(Int32 id)");
swDAL.WriteLine("       {");
swDAL.WriteLine("           BE result = new BE();");
swDAL.WriteLine("           using (IDbConnection connection = DataConnection.Connection())");
swDAL.WriteLine("           {");
swDAL.WriteLine("               String sqlQuery = String.Format(\"SELECT * FROM {0} WHERE {1}=@" + 
                key + "\", _tableName, _" + key + ");");
swDAL.WriteLine("               IDbCommand command = DataConnection.Command(connection, sqlQuery);");
swDAL.WriteLine("               AddParameter(command, \"" + key + "\", id );");
swDAL.WriteLine("               connection.Open();");
swDAL.WriteLine("               IDataReader reader = command.ExecuteReader();");
swDAL.WriteLine("               while (reader.Read())");
swDAL.WriteLine("               {");
swDAL.WriteLine("                   result = ToObject(reader);");
swDAL.WriteLine("               }");
swDAL.WriteLine("           }");
swDAL.WriteLine("           if (result." + key + " > 0)");
swDAL.WriteLine("           {");
swDAL.WriteLine("               return LoadObject(result);");
swDAL.WriteLine("           }");
swDAL.WriteLine("           else");
swDAL.WriteLine("           {");
swDAL.WriteLine("               return null;");
swDAL.WriteLine("           }");
swDAL.WriteLine("       }");
swDAL.WriteLine("       #endregion");
swDAL.WriteLine("");

关于此代码的一些说明

每个方法始终返回同类对象或这些同类对象的列表。换句话说,在我们客户类的 DAL 中,每个方法都返回一个“customer”类型的对象,或者客户对象的列表。

调用 ToObject() 方法返回该类对象的一个实例。LoadObject() 方法只是将我们的对象强制转换为我们正在使用的类的类型。

您会看到几个可能需要简要解释的方法。

DataAccessObject 类

DataAccessObject 包含处理数据库调用参数化和数据类型转换(例如,图像到字节数组及其返回)的方法。

DataConnection 类

DataConnection 类包含处理连接字符串和数据提供程序的方法,并链接到我们在 BE 层中定义的 AdoDotNetDataProvider

关于 UI 代码的一点说明

该工具的当前版本生成的 UI 代码假定您使用的是 DevExpress WinForms 控件套件。如果足够多人请求,我将添加对 Visual Studio 原生标准 Microsoft 控件的支持。该工具生成的 BE/BLL/DAL 代码可用于所有类型的应用程序;只有 UI 代码是 WinForm 特定的。

连接所有内容

开始之前,创建一个文件夹用于存放您的 Visual Studio 解决方案。运行 ORM Tool 可执行文件,将每个层的结果放在其自己的项目中,这些项目将驻留在解决方案文件夹内的各自文件夹中。(该工具将自动提示您)。

如下建立每个项目的连接引用

  • 在 BLL 项目中,添加对 BE 和 DAL 项目的引用。
  • 在 DAL 项目中,添加对 BE 项目的引用。
  • 在您的 UI 项目中,添加对 BE 和 BLL 项目的引用。

编译每个项目,然后您就可以开始创建 GUI 窗体了。如果您拥有 DevExpress WinForms 库,您可以勾选以创建 UI 层,该工具将为 BE 层中的每个类创建浏览和 CRUD 窗体。

如前所述,如果您在数据库表名中使用复数形式,则需要在每个表的 DAL 中进行少量更改。

private static String _tableName = "Customers";
// you will need to add the 's' (or other plural form)

您可能还想尝试其他操作。您可以不选择数据库表,而是选择一个包含您要使用的表字段规范的文本文件。如果有很多文本文件,每个表一个。将它们放在解决方案结构外部的文件夹中,并将类名留空。该工具将知道依次打开每个文本文件,并为每个文件构建 BE/BLL/DAL/UI 类集。

未来功能

您会注意到的一件事是,您一次只能为一个数据库表构建代码。当然,您可以为数据库中的每个表重复这些步骤,就像我现在做的那样,但我认为如果我添加一些代码允许您指向一个数据库,然后它为找到的每个表构建代码,那将会有帮助。我不确定我何时会完成这项工作,因为工作总会以某种方式打断生活中的好事,但如果您会使用它,请给我发请求。

历史

尽管我们使用此工具已超过 3 年,但这却是第一次发布到“大众”。

© . All rights reserved.