代码自动生成工具MyGeneration之一(程序员必备工具)

时间:2024-03-08 16:45:29
代码自动生成工具MyGeneration之一(程序员必备工具)

分类: C#2008-08-06 18:12 16064人阅读 评论(12) 收藏 举报

工具数据库相关数据库stringbrowser存储

   前段时间用C#做网站,用到了大量数据库相关的东西。网站采用3层结构,即数据访问层(Data Access Layer),业务逻辑层(Business Logic Layer),页面表现层().做了一段时间,发现向数据访问层和业务逻辑层加入新的类,数据库的表结构改了,还要对应的修改数据访问层和业务逻辑层的代码,这个工作很是繁琐,无聊,而且容易出错。做了几次之后就想有什么办法可以让机器自动完成呢?

  联想到以前看过Java似乎有个Hibernate,可以很方便的实现对象关系映射(ORM),即自动的从数据库的表生成对应的对象,.Net也应该有类似的功能吧。于是找啊找,发现了很多.Net的ORM工具,不过都有缺点,就是代码得依赖于那些ORM工具,我希望能够让机器按我的要求生成我自己的代码,这样就更加灵活了。

  于是乎,发现了CodeSmith和MyGeneration,CodeSmith是 网上传的.NET 程序员十种必备工具之一,我们写代码时,经常需要重复完成某些特定的任务,例如编写数据访问代码或者生成自定义集合。我们可以用CodeSmith编写模板自动完成这些任务,从而不仅提高工作效率,而且能够自动完成那些最为乏味的任务。可惜,CodeSmith是需要注册的,试用版只能用15天。而MyGeneration基本上和CodeSmith的功能差不多哦,但是他是开源的。我选软件的原则是能开源免费的就用,实在没替代了才选那些需要注册的,有版权的软件。所以就选MyGeneration了。

  用过一段时间后感觉MyGeneration主要是为了自动生成数据库相关的代码的,可能C#用得比较多,其实我们可以用它生成任何代码,C++,JavaScript...而且还不仅仅局限于数据库,其他方面的代码也可以用MyGeneration自动生成。比如我们经常用数据访问层和业务逻辑层,用MyGeneration就可以自动生成这些代码,我们可以不用手动写代码了。比如数据访问层,我们需要调用一个存储过程,用MyGeneration我们只需要选择生成存储过程代码的模板,执行一下脚本,然后在界面上选择数据库上某个存储过程,然后就自动生成了数据库访问代码,整个过程只需要点几下鼠标,代码就自动生成了。这对于需要大量操作数据库的程序员来说,效率是多大的提升啊。

  废话少说,还是来点实在的吧。首先声明,我的MyGeneration版本是:1.3.0.3

  安装完MyGeneration后,第一次启动会要求进行一些数据库相关的配置。如图:

  ConnectionString: 就是指定连接哪个数据库了,填好这个就可以点确定了。

  下面来看一看其他的项都是什么。

  Language Mapping:就是指定数据库和对象基本类型的映射关系。让我们打开Languages.xml文件看一下吧:

  1. <Language From="SQL" To="C#">
  2. <Type From="bigint" To="long" />
  3. <Type From="binary" To="object" />
  4. <Type From="bit" To="bool" />
  5. <Type From="char" To="string" />
  6. <Type From="datetime" To="DateTime" />
  7. <Type From="decimal" To="decimal" />
  8. <Type From="float" To="double" />
  9. <Type From="image" To="byte[]" />
  10. <Type From="int" To="int" />
  11. <Type From="money" To="decimal" />
  12. <Type From="nchar" To="string" />
  13. <Type From="ntext" To="string" />
  14. <Type From="numeric" To="decimal" />
  15. <Type From="nvarchar" To="string" />
  16. <Type From="real" To="float" />
  17. <Type From="smalldatetime" To="DateTime" />
  18. <Type From="smallint" To="short" />
  19. <Type From="smallmoney" To="decimal" />
  20. <Type From="text" To="string" />
  21. <Type From="timestamp" To="byte[]" />
  22. <Type From="tinyint" To="byte" />
  23. <Type From="uniqueidentifier" To="Guid" />
  24. <Type From="varbinary" To="byte[]" />
  25. <Type From="varchar" To="string" />
  26. <Type From="xml" To="string" />
  27. <Type From="sql_variant" To="object" />
  28. </Language>

  这是里面的一段内容,很明显,是数据库SQL的字段转到C#是什么类型,里面没有C++的,假如我们要让它支持C++的话,需要在这里加入SQL到C++的类型转换。

  Database Target Mapping:先看里面的内容吧:

  1. <DbTarget From="ACCESS" To="DAO">
  2. <Type From="Text" To="DAO.dbText" />
  3. <Type From="Memo" To="DAO.dbMemo" />
  4. <Type From="DateTime" To="DAO.dbDate" />
  5. <Type From="Currency" To="DAO.dbCurrency" />
  6. <Type From="Yes/No" To="DAO.dbBoolean" />
  7. <Type From="OLE Object" To="DAO.dbLongBinary" />
  8. <Type From="Hyperlink" To="DAO.dbMemo" />
  9. <Type From="Double" To="DAO.dbDouble" />
  10. <Type From="Replication ID" To="DAO.dbGUID" />
  11. <Type From="Long" To="DAO.dbLong" />
  12. <Type From="Single" To="DAO.dbSingle" />
  13. <Type From="Decimal" To="DAO.dbDecimal" />
  14. <Type From="Byte" To="DAO.dbByte" />
  15. <Type From="Integer" To="DAO.dbInteger" />
  16. </DbTarget>

  呵呵,一目了然,就是Access数据库用DAO的方式访问,数据库的列的类型对应的DAO里是什么类型。

  UseMetaData目前没什么用。

  看看MyGeneration的界面吧:

   Template Browser 面板 列出了一些模板,这是自动生成代码需要用到的模板。安装的时候会自己带很多模板。

   MyMeta Browser则列出了当前连接的数据库上有些什么库,表,存储过程。

   工作区则是具体模板对应的代码。

   先让我们体验一下吧。

   展开Template Browser面板下"d00dads - C#", 双击 “d00dads - Invoke a Stored Procedure", 让工作区显示其内容,

然后点击工具栏上的 "Execute" 按钮,如图红框所示:

  弹出对话框,如图:

  选择数据库,存储过程,存储过程类型,点确定(OK)。

  然后可以看到工作区 Output 里输出了代码了。例如:

  1. using System.Data;
  2. using System.Collections.Specialized;  
  3. using System.Data.SqlClient;       
  4. public virtual void dm_exec_cursors (int spid)
  5.         {
  6.             ListDictionary parameters = new ListDictionary();
  7.             parameters.Add( new SqlParameter("@spid", SqlDbType.Int, 0), spid);
  8.             LoadFromSqlNoExec("dm_exec_cursors", parameters);
  9.         }

  这就是MyGeneration自动获取了存储过程的输入参数,然后在代码里构造相应的参数,然后生成的代码。

  这只是MyGeneration自带的模板生成的,大家可以试一试其他的模板的效果。

  里面有自动根据表结构生成BLL的类......看下效果:

  1. /*
  2. \'===============================================================================
  3. \'  Generated From - CSharp_dOOdads_BusinessEntity.vbgen
  4. \'
  5. \'  ** IMPORTANT  **
  6. \'  How to Generate your stored procedures:
  7. \'
  8. \'  SQL        = SQL_StoredProcs.vbgen
  9. \'  ACCESS     = Access_StoredProcs.vbgen
  10. \'  ORACLE     = Oracle_StoredProcs.vbgen
  11. \'  FIREBIRD   = FirebirdStoredProcs.vbgen
  12. \'  POSTGRESQL = PostgreSQL_StoredProcs.vbgen
  13. \'
  14. \'  The supporting base class OleDbEntity is in the Architecture directory in "dOOdads".
  15. \' 
  16. \'  This object is \'abstract\' which means you need to inherit from it to be able
  17. \'  to instantiate it.  This is very easilly done. You can override properties and
  18. \'  methods in your derived class, this allows you to regenerate this class at any
  19. \'  time and not worry about overwriting custom code.
  20. \'
  21. \'  NEVER EDIT THIS FILE.
  22. \'
  23. \'  public class YourObject :  _YourObject
  24. \'  {
  25. \'
  26. \'  }
  27. \'
  28. \'===============================================================================
  29. */
  30. // Generated by MyGeneration Version # (1.3.0.3)
  31. using System;
  32. using System.Data;
  33. using System.Data.OleDb;
  34. using System.Collections;
  35. using System.Collections.Specialized;
  36. using MyGeneration.dOOdads;
  37. namespace Your.Namespace
  38. {
  39. public abstract class _Users : OleDbEntity
  40.     {
  41. public _Users()
  42.         {
  43. this.QuerySource = "Users";
  44. this.MappingName = "Users";
  45.         }  
  46. //=================================================================
  47. //  public Overrides void AddNew()
  48. //=================================================================
  49. //
  50. //=================================================================
  51. public override void AddNew()
  52.         {
  53. base.AddNew();
  54.         }
  55. public override string GetAutoKeyColumn()
  56.         {
  57. return "ID";
  58.         }
  59. public override void FlushData()
  60.         {
  61. this._whereClause = null;
  62. this._aggregateClause = null;
  63. base.FlushData();
  64.         }
  65. //=================================================================
  66. //      public Function LoadAll() As Boolean
  67. //=================================================================
  68. //  Loads all of the records in the database, and sets the currentRow to the first row
  69. //=================================================================
  70. public bool LoadAll()
  71.         {
  72.             ListDictionary parameters = null;
  73. return base.LoadFromSql("[" + this.SchemaStoredProcedure + "proc_UsersLoadAll]", parameters);
  74.         }
  75. //=================================================================
  76. // public Overridable Function LoadByPrimaryKey()  As Boolean
  77. //=================================================================
  78. //  Loads a single row of via the primary key
  79. //=================================================================
  80. public virtual bool LoadByPrimaryKey()
  81.         {
  82.             ListDictionary parameters = new ListDictionary();
  83. return base.LoadFromSql("[" + this.SchemaStoredProcedure + "proc_UsersLoadByPrimaryKey]", parameters);
  84.         }
  85.         #region Parameters
  86. protected class Parameters
  87.         {
  88. public static OleDbParameter ID
  89.             {
  90. get
  91.                 {
  92. return new OleDbParameter("@ID", OleDbType.Integer, 0);
  93.                 }
  94.             }
  95. public static OleDbParameter Alias
  96.             {
  97. get
  98.                 {
  99. return new OleDbParameter("@Alias", OleDbType.VarChar, 2147483647);
  100.                 }
  101.             }
  102.         }
  103.         #endregion     
  104.         #region ColumnNames
  105. public class ColumnNames
  106.         { 
  107. public const string ID = "ID";
  108. public const string Alias = "Alias";
  109. static public string ToPropertyName(string columnName)
  110.             {
  111. if(ht == null)
  112.                 {
  113.                     ht = new Hashtable();
  114.                     ht[ID] = _Users.PropertyNames.ID;
  115.                     ht[Alias] = _Users.PropertyNames.Alias;
  116.                 }
  117. return (string)ht[columnName];
  118.             }
  119. static private Hashtable ht = null;         
  120.         }
  121.         #endregion
  122.         #region PropertyNames
  123. public class PropertyNames
  124.         { 
  125. public const string ID = "ID";
  126. public const string Alias = "Alias";
  127. static public string ToColumnName(string propertyName)
  128.             {
  129. if(ht == null)
  130.                 {
  131.                     ht = new Hashtable();
  132.                     ht[ID] = _Users.ColumnNames.ID;
  133.                     ht[Alias] = _Users.ColumnNames.Alias;
  134.                 }
  135. return (string)ht[propertyName];
  136.             }
  137. static private Hashtable ht = null;         
  138.         }           
  139.         #endregion 
  140.         #region StringPropertyNames
  141. public class StringPropertyNames
  142.         { 
  143. public const string ID = "s_ID";
  144. public const string Alias = "s_Alias";
  145.         }
  146.         #endregion     
  147.         #region Properties
  148. public virtual Integer ID
  149.         {
  150. get
  151.             {
  152. return base.GetInteger(ColumnNames.ID);
  153.             }
  154. set
  155.             {
  156. base.SetInteger(ColumnNames.ID, value);
  157.             }
  158.         }
  159. public virtual String Alias
  160.         {
  161. get
  162.             {
  163. return base.GetString(ColumnNames.Alias);
  164.             }
  165. set
  166.             {
  167. base.SetString(ColumnNames.Alias, value);
  168.             }
  169.         }
  170.         #endregion
  171.         #region String Properties
  172. public virtual string s_ID
  173.         {
  174. get
  175.             {
  176. return this.IsColumnNull(ColumnNames.ID) ? string.Empty : base.GetIntegerAsString(ColumnNames.ID);
  177.             }
  178. set
  179.             {
  180. if(string.Empty == value)
  181. this.SetColumnNull(ColumnNames.ID);
  182. else
  183. this.ID = base.SetIntegerAsString(ColumnNames.ID, value);
  184.             }
  185.         }
  186. public virtual string s_Alias
  187.         {
  188. get
  189.             {
  190. return this.IsColumnNull(ColumnNames.Alias) ? string.Empty : base.GetStringAsString(ColumnNames.Alias);
  191.             }
  192. set
  193.             {
  194. if(string.Empty == value)
  195. this.SetColumnNull(ColumnNames.Alias);
  196. else
  197. this.Alias = base.SetStringAsString(ColumnNames.Alias, value);
  198.             }
  199.         }
  200.         #endregion      
  201. private AggregateClause _aggregateClause = null;   
  202.         #endregion
  203. protected override IDbCommand GetInsertCommand()
  204.         {
  205.             OleDbCommand cmd = new OleDbCommand();
  206.             cmd.CommandType = CommandType.StoredProcedure;
  207.             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersInsert]";
  208.             CreateParameters(cmd);
  209. return cmd;
  210.         }
  211. protected override IDbCommand GetUpdateCommand()
  212.         {
  213.             OleDbCommand cmd = new OleDbCommand();
  214.             cmd.CommandType = CommandType.StoredProcedure;
  215.             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersUpdate]";
  216.             CreateParameters(cmd);
  217. return cmd;
  218.         }
  219. protected override IDbCommand GetDeleteCommand()
  220.         {
  221.             OleDbCommand cmd = new OleDbCommand();
  222.             cmd.CommandType = CommandType.StoredProcedure;
  223.             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersDelete]";
  224.             OleDbParameter p;
  225. return cmd;
  226.         }
  227. private IDbCommand CreateParameters(OleDbCommand cmd)
  228.         {
  229.             OleDbParameter p;
  230.             p = cmd.Parameters.Add(Parameters.ID);
  231.             p.SourceColumn = ColumnNames.ID;
  232.             p.SourceVersion = DataRowVersion.Current;
  233.             p = cmd.Parameters.Add(Parameters.Alias);
  234.             p.SourceColumn = ColumnNames.Alias;
  235.             p.SourceVersion = DataRowVersion.Current;
  236. return cmd;
  237.         }
  238.     }
  239. }

   这就是自动获得表结构,然后从字段映射成类里面的成员,并且还有一些插入,更新,删除的代码。

   当然自带的模板生成的代码不一定符合我们的需要,但是我们可以根据需要自己写一些模板来生成符合自己需要的代码,这也是非常容易的事,欲知如何实现,请看下回文章。

代码自动生成工具MyGeneration之二