代码自动生成工具MyGeneration之一

  前段时间用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面板下"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         
 5                 
 6         
 7         public virtual void dm_exec_cursors (int spid)
 8         {
 9             ListDictionary parameters = new ListDictionary();
10             
11             parameters.Add( new SqlParameter("@spid", SqlDbType.Int, 0), spid);
12             LoadFromSqlNoExec("dm_exec_cursors", parameters);
13         }

这就是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         }
 56         
 57         
 58         public override string GetAutoKeyColumn()
 59         {
 60             return "ID";
 61         }
 62         public override void FlushData()
 63         {
 64             this._whereClause = null;
 65             this._aggregateClause = null;
 66             base.FlushData();
 67         }
 68         
 69         //=================================================================
 70         //      public Function LoadAll() As Boolean
 71         //=================================================================
 72         //  Loads all of the records in the database, and sets the currentRow to the first row
 73         //=================================================================
 74         public bool LoadAll() 
 75         {
 76             ListDictionary parameters = null;
 77             
 78             return base.LoadFromSql("[" + this.SchemaStoredProcedure + "proc_UsersLoadAll]", parameters);
 79         }
 80     
 81         //=================================================================
 82         // public Overridable Function LoadByPrimaryKey()  As Boolean
 83         //=================================================================
 84         //  Loads a single row of via the primary key
 85         //=================================================================
 86         public virtual bool LoadByPrimaryKey()
 87         {
 88             ListDictionary parameters = new ListDictionary();
 89                     
 90             return base.LoadFromSql("[" + this.SchemaStoredProcedure + "proc_UsersLoadByPrimaryKey]", parameters);
 91         }
 92         
 93         #region Parameters
 94         protected class Parameters
 95         {
 96             
 97             public static OleDbParameter ID
 98             {
 99                 get
100                 {
101                     return new OleDbParameter("@ID", OleDbType.Integer, 0);
102                 }
103             }
104             
105             public static OleDbParameter Alias
106             {
107                 get
108                 {
109                     return new OleDbParameter("@Alias", OleDbType.VarChar, 2147483647);
110                 }
111             }
112             
113         }
114         #endregion      
115     
116         #region ColumnNames
117         public class ColumnNames
118         {  
119             public const string ID = "ID";
120             public const string Alias = "Alias";
121             static public string ToPropertyName(string columnName)
122             {
123                 if(ht == null)
124                 {
125                     ht = new Hashtable();
126                     
127                     ht[ID] = _Users.PropertyNames.ID;
128                     ht[Alias] = _Users.PropertyNames.Alias;
129                 }
130                 return (string)ht[columnName];
131             }
132             static private Hashtable ht = null;          
133         }
134         #endregion
135         
136         #region PropertyNames
137         public class PropertyNames
138         {  
139             public const string ID = "ID";
140             public const string Alias = "Alias";
141             static public string ToColumnName(string propertyName)
142             {
143                 if(ht == null)
144                 {
145                     ht = new Hashtable();
146                     
147                     ht[ID] = _Users.ColumnNames.ID;
148                     ht[Alias] = _Users.ColumnNames.Alias;
149                 }
150                 return (string)ht[propertyName];
151             }
152             static private Hashtable ht = null;          
153         }            
154         #endregion  
155         #region StringPropertyNames
156         public class StringPropertyNames
157         {  
158             public const string ID = "s_ID";
159             public const string Alias = "s_Alias";
160         }
161         #endregion      
162         
163         #region Properties
164     
165         public virtual Integer ID
166         {
167             get
168             {
169                 return base.GetInteger(ColumnNames.ID);
170             }
171             set
172             {
173                 base.SetInteger(ColumnNames.ID, value);
174             }
175         }
176         public virtual String Alias
177         {
178             get
179             {
180                 return base.GetString(ColumnNames.Alias);
181             }
182             set
183             {
184                 base.SetString(ColumnNames.Alias, value);
185             }
186         }
187         #endregion
188         
189         #region String Properties
190     
191         public virtual string s_ID
192         {
193             get
194             {
195                 return this.IsColumnNull(ColumnNames.ID) ? string.Empty : base.GetIntegerAsString(ColumnNames.ID);
196             }
197             set
198             {
199                 if(string.Empty == value)
200                     this.SetColumnNull(ColumnNames.ID);
201                 else
202                     this.ID = base.SetIntegerAsString(ColumnNames.ID, value);
203             }
204         }
205         public virtual string s_Alias
206         {
207             get
208             {
209                 return this.IsColumnNull(ColumnNames.Alias) ? string.Empty : base.GetStringAsString(ColumnNames.Alias);
210             }
211             set
212             {
213                 if(string.Empty == value)
214                     this.SetColumnNull(ColumnNames.Alias);
215                 else
216                     this.Alias = base.SetStringAsString(ColumnNames.Alias, value);
217             }
218         }
219         #endregion      
220     
221         
222         private AggregateClause _aggregateClause = null;    
223         #endregion
224     
225         protected override IDbCommand GetInsertCommand() 
226         {
227         
228             OleDbCommand cmd = new OleDbCommand();
229             cmd.CommandType = CommandType.StoredProcedure;
230             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersInsert]";
231     
232             CreateParameters(cmd);
233                 
234             return cmd;
235         }
236     
237         protected override IDbCommand GetUpdateCommand()
238         {
239         
240             OleDbCommand cmd = new OleDbCommand();
241             cmd.CommandType = CommandType.StoredProcedure;
242             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersUpdate]";
243     
244             CreateParameters(cmd);
245                   
246             return cmd;
247         }
248     
249         protected override IDbCommand GetDeleteCommand()
250         {
251         
252             OleDbCommand cmd = new OleDbCommand();
253             cmd.CommandType = CommandType.StoredProcedure;
254             cmd.CommandText = "[" + this.SchemaStoredProcedure + "proc_UsersDelete]";
255     
256             OleDbParameter p;
257   
258             return cmd;
259         }
260         
261         private IDbCommand CreateParameters(OleDbCommand cmd)
262         {
263             OleDbParameter p;
264         
265             p = cmd.Parameters.Add(Parameters.ID);
266             p.SourceColumn = ColumnNames.ID;
267             p.SourceVersion = DataRowVersion.Current;
268             p = cmd.Parameters.Add(Parameters.Alias);
269             p.SourceColumn = ColumnNames.Alias;
270             p.SourceVersion = DataRowVersion.Current;
271             return cmd;
272         }
273     }
274 }

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

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

本文转载自:http://blog.csdn.net/zxcred/article/details/2778193

原文地址:https://www.cnblogs.com/qiernonstop/p/3630090.html