• 【转】打造你自己的代码生成器


    网络上有很多的自动生成代码的工具,有基于模板的像MyGeneration、CodeSmith,有基于自己写的架构的像动软的,都是很好的代码 生成工具。但是一般在公司里面我们都有自己的架构,所以如何基于自己的架构生成代码呢?如果你熟悉MyGeneration等工具的模板制作,就可以做个 模板然后也可以生成代码。如果不熟悉这个模板工具,可能要花费一些时间来学习如何制作模板。

     我个人喜欢自己写点代码,不妨制作自己的代码生成器。

    首先,我们需要有获取数据库、数据表信息的sql。(以下都已SQL2005为例)。
    1、获取服务器上所有的数据库:select name as dbName from sysdatabases order by name
    注意:此时的数据库连接字符串需要连接master库,因为所有的库信息都保存在系统库中。
    2、获取库中所有表:
    select [name] from sysObjects where xtype='U'and [name]<>'dtproperties' order by [name]
    注意:此时的连接字符串中的库连接的是你要操作的库,已经不是master了。
    3、获取表的字段信息:
    SELECT colorder=C.column_id,ColumnName=C.name,TypeName=T.name, Length=C.max_length, Preci=C.precision, Scale=C.scale, IsIdentity=CASE WHEN C.is_identity=1 THEN N'1'ELSE N'' END,isPK=ISNULL(IDX.PrimaryKey,N''),Computed=CASE WHEN C.is_computed=1 THEN N'1'ELSE N'' END, IndexName=ISNULL(IDX.IndexName,N''), IndexSort=ISNULL(IDX.Sort,N''), Create_Date=O.Create_Date, Modify_Date=O.Modify_date, cisNull=CASE WHEN C.is_nullable=1 THEN N'1'ELSE N'' END, defaultVal=ISNULL(D.definition,N''), deText=ISNULL(PFD.[value],N'') FROM sys.columns C INNER JOIN sys.objects O ON C.[object_id]=O.[object_id] AND O.type='U' AND O.is_ms_shipped=0 INNER JOIN sys.types T ON C.user_type_id=T.user_type_id LEFT JOIN sys.default_constraints D ON C.[object_id]=D.parent_object_id AND C.column_id=D.parent_column_id AND C.default_object_id=D.[object_id] LEFT JOIN sys.extended_properties PFD ON PFD.class=1 AND C.[object_id]=PFD.major_id AND C.column_id=PFD.minor_id LEFT JOIN sys.extended_properties PTB ON PTB.class=1 AND PTB.minor_id=0 AND C.[object_id]=PTB.major_id LEFT JOIN ( SELECT IDXC.[object_id], IDXC.column_id, Sort=CASE INDEXKEY_PROPERTY(IDXC.[object_id],IDXC.index_id,IDXC.index_column_id,'IsDescending') WHEN 1 THEN 'DESC' WHEN 0 THEN 'ASC' ELSE '' END, PrimaryKey=CASE WHEN IDX.is_primary_key=1 THEN N'1'ELSE N'' END, IndexName=IDX.Name FROM sys.indexes IDX INNER JOIN sys.index_columns IDXC ON IDX.[object_id]=IDXC.[object_id] AND IDX.index_id=IDXC.index_id LEFT JOIN sys.key_constraints KC ON IDX.[object_id]=KC.[parent_object_id] AND IDX.index_id=KC.unique_index_id INNER JOIN ( SELECT [object_id], Column_id, index_id=MIN(index_id) FROM sys.index_columns GROUP BY [object_id], Column_id ) IDXCUQ ON IDXC.[object_id]=IDXCUQ.[object_id] AND IDXC.Column_id=IDXCUQ.Column_id AND IDXC.index_id=IDXCUQ.index_id ) IDX ON C.[object_id]=IDX.[object_id] AND C.column_id=IDX.column_id WHERE O.name=N'YourTablelName' ORDER BY O.name,C.column_id
    这个sql有点超长,里面YourTablelName换成你自己的表名即可获得表的字段信息。

    其次,现在我们就可以通过上面的三条基本的sql,就可以获得我们生成代码所需的信息,还等什么,开写。
    封装一个简单的query。
    public DataSet Query(string sqlStr)
    {
     SqlDataAdapter sda = null;
     System.Data.SqlClient.SqlConnection sqlConn = new System.Data.SqlClient.SqlConnection();

     connStr = "Data Source=127.0.01;Initial Catalog=testDb;User ID=sa;Password=sa;";

     sqlConn.ConnectionString = connStr;
     try
     {
      DataSet ds = new DataSet();
      sda = new SqlDataAdapter(sqlStr,sqlConn);
      sda.Fill(ds);
      sda.Dispose();
      return ds;
     }
     catch(Exception e)
     {
      return null;
     }
     finally
     {
      sqlConn.Close();
     }
    }
    通过这个简单的query,我们就可以获得需要生成代码的表信息。

    最后,通过循环DataSet中的信息,我们可以获得字段的名称、类型、长度、是否可空、是否主键、是否自增列、备注的相关信息,就可以按着我们的 自己的架构来生成代码了。包括生成数据操作层,当然我们也可以按着自己的架构把aspx页面和aspx.cs等等都生成出来。因为aspx和 aspx.cs无非就是纯文本文件,甚至我们也可以仿造动软的模式将项目的方案(sln)都生成出来,只要我们先打开这些文件,看看就明白了。

    下面这段代码可以根据你自己的需要生成部分aspx页面,包括了必录控件和格式校验控件。
    foreach (DataRow row1 in clmnInfoList.Rows)
    {
     string clmnName = row1["ColumnName"].ToString();
     string clmnTypeName = row1["TypeName"].ToString();
     string isIdentity = row1["IsIdentity"].ToString();
     string clmnLen = row1["Length"].ToString();
     string clmnPreci = row1["Preci"].ToString();
     string clmnScale = row1["Scale"].ToString();
     string isPkClmn = row1["isPK"].ToString();
     string allowNull = row1["cisNull"].ToString();
     string defaultVal = row1["defaultVal"].ToString();
     string desc = row1["deText"].ToString();

     //跳过自增类
     if(isIdentity.Equals("1"))
     {
      continue;
     }

     templateStr += "          <TR>/r/n";
     templateStr += "           <TD height=/"25/" align=/"right/" width=/"25%/">/r/n";
     templateStr += "            <asp:label id=/"lbl" + clmnName + "/" runat=/"server/" CssClass=/"tttable/">" + (desc.Equals("") ? clmnName : desc) + "</asp:label></TD>/r/n";
     templateStr += "           <TD height=/"25/">/r/n";
     if(clmnTypeName.Equals("nvarchar"))
     {
      templateStr += "            <asp:textbox id=/"txt" + clmnName + "/" runat=/"server/" CssClass=/"edline/" Width=/"320px/" MaxLength=/"" + clmnLen + "/"></asp:textbox>/r/n";
      
      //必录项
      if(allowNull.Equals(""))
       templateStr += "            <asp:requiredfieldvalidator id=/"require" + clmnName + "/" runat=/"server/" ControlToValidate=/"txt" + clmnName + "/">*</asp:requiredfieldvalidator>/r/n";
     }
     else if(clmnTypeName.Equals("datetime"))
     {
      templateStr += "            <asp:textbox id=/"txt" + clmnName + "/" runat=/"server/" CssClass=/"edline/" Width=/"320px/" MaxLength=/"10/"></asp:textbox>/r/n";
      
      //必录项
      if(allowNull.Equals(""))
       templateStr += "            <asp:requiredfieldvalidator id=/"require" + clmnName + "/" runat=/"server/" ControlToValidate=/"txt" + clmnName + "/">*</asp:requiredfieldvalidator>/r/n";
      //日期格式校验
      templateStr += "            <asp:RangeValidator id=/"range" + clmnName + "/" runat=/"server/" ErrorMessage=/"请输入合法日期/" Type=/"Date/" MinimumValue=/"1990-1-1/" MaximumValue=/"9999-12-31/" ControlToValidate=/"txt" + clmnName + "/" Display=/"Dynamic/"></asp:RangeValidator>/r/n";
     }

     templateStr += "           </TD>/r/n";
     templateStr += "          </TR>/r/n";
    }

    补充:
    现在我们好多代码都是一个表一个对象的来封装,还包括一些表的关联关系,那么这部分代码是否也能一次生成?这就需要我们来获得表的外键以及依赖关系。

    获取表的外键:
    SELECT     fk.name AS fkname, ftable.name AS tblName, cn.name AS clmn, rtable.name relationTblName, (SELECT     name
                                FROM           syscolumns
                                WHERE       sysforeignkeys.rkeyid =  syscolumns.id AND  sysforeignkeys.rkey =  syscolumns.colid) relationClmn
    FROM         sysforeignkeys INNER JOIN
                          sysobjects AS fk ON sysforeignkeys.constid = fk.id INNER JOIN
                          sysobjects AS ftable ON  sysforeignkeys.fkeyid = ftable.id INNER JOIN
                          sysobjects AS rtable ON  sysforeignkeys.rkeyid = rtable.id INNER JOIN
                          syscolumns AS cn ON sysforeignkeys.fkeyid = cn.id AND sysforeignkeys.fkey = cn.colid
    where ftable.name='YourTableName'

    获取表的被依赖关系:
    SELECT     fk.name AS fkname, ftable.name AS tblName, cn.name AS clmn, rtable.name relationTblName, (SELECT     name
                                FROM           syscolumns
                                WHERE       sysforeignkeys.rkeyid =  syscolumns.id AND  sysforeignkeys.rkey =  syscolumns.colid) relationClmn
    FROM          sysforeignkeys INNER JOIN
                           sysobjects AS fk ON  sysforeignkeys.constid = fk.id INNER JOIN
                           sysobjects AS ftable ON  sysforeignkeys.fkeyid = ftable.id INNER JOIN
                           sysobjects AS rtable ON  sysforeignkeys.rkeyid = rtable.id INNER JOIN
                           syscolumns AS cn ON  sysforeignkeys.fkeyid = cn.id AND  sysforeignkeys.fkey = cn.colid
    where rtable.name='YourTableName'


    通过这个sql就可以获得表的外键关联表和关联字段,这样和前面我们获得的字段的信息结合起来使用后就可以生成我们所需要的父子表关系了。

    转至http://blog.csdn.net/sunearlier/article/details/2967649

  • 相关阅读:
    Arcgis中修改字段名方法
    题事件名称为CLR20r3
    【转】CLR20R3 程序终止的几种解决方案
    Ajax+asp.net无刷新验证用户名
    [转载]C/C++编译器cl.exe的命令选项
    [网络整理]DEBUG命令使用解析五
    [网络整理]DEBUG命令使用解析一
    [网络整理]DEBUG命令使用解析六
    [易学C#]C#3.0语言新特性
    [易学C#]C#3.0语言新特性之Lambda表达式
  • 原文地址:https://www.cnblogs.com/58soft/p/3217576.html
Copyright © 2020-2023  润新知