前段时间用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文件看一下吧:
- < Language From = "SQL" To = "C#" >
- < Type From = "bigint" To = "long" />
- < Type From = "binary" To = "object" />
- < Type From = "bit" To = "bool" />
- < Type From = "char" To = "string" />
- < Type From = "datetime" To = "DateTime" />
- < Type From = "decimal" To = "decimal" />
- < Type From = "float" To = "double" />
- < Type From = "image" To = "byte[]" />
- < Type From = "int" To = "int" />
- < Type From = "money" To = "decimal" />
- < Type From = "nchar" To = "string" />
- < Type From = "ntext" To = "string" />
- < Type From = "numeric" To = "decimal" />
- < Type From = "nvarchar" To = "string" />
- < Type From = "real" To = "float" />
- < Type From = "smalldatetime" To = "DateTime" />
- < Type From = "smallint" To = "short" />
- < Type From = "smallmoney" To = "decimal" />
- < Type From = "text" To = "string" />
- < Type From = "timestamp" To = "byte[]" />
- < Type From = "tinyint" To = "byte" />
- < Type From = "uniqueidentifier" To = "Guid" />
- < Type From = "varbinary" To = "byte[]" />
- < Type From = "varchar" To = "string" />
- < Type From = "xml" To = "string" />
- < Type From = "sql_variant" To = "object" />
- </ Language >
这是里面的一段内容,很明显,是数据库SQL的字段转到C#是什么类型,里面没有C++的,假如我们要让它支持C++的话,需要在这里加入SQL到C++的类型转换。
Database Target Mapping:先看里面的内容吧:
- < DbTarget From = "ACCESS" To = "DAO" >
- < Type From = "Text" To = "DAO.dbText" />
- < Type From = "Memo" To = "DAO.dbMemo" />
- < Type From = "DateTime" To = "DAO.dbDate" />
- < Type From = "Currency" To = "DAO.dbCurrency" />
- < Type From = "Yes/No" To = "DAO.dbBoolean" />
- < Type From = "OLE Object" To = "DAO.dbLongBinary" />
- < Type From = "Hyperlink" To = "DAO.dbMemo" />
- < Type From = "Double" To = "DAO.dbDouble" />
- < Type From = "Replication ID" To = "DAO.dbGUID" />
- < Type From = "Long" To = "DAO.dbLong" />
- < Type From = "Single" To = "DAO.dbSingle" />
- < Type From = "Decimal" To = "DAO.dbDecimal" />
- < Type From = "Byte" To = "DAO.dbByte" />
- < Type From = "Integer" To = "DAO.dbInteger" />
- </ DbTarget >
呵呵,一目了然,就是Access数据库用DAO的方式访问,数据库的列的类型对应的DAO里是什么类型。
UseMetaData目前没什么用。
看看MyGeneration的界面吧:
Template Browser 面板 列出了一些模板,这是自动生成代码需要用到的模板。安装的时候会自己带很多模板。
MyMeta Browser则列出了当前连接的数据库上有些什么库,表,存储过程。
工作区则是具体模板对应的代码。
先让我们体验一下吧。
展开Template Browser面板下"d00dads - C#", 双击 “d00dads - Invoke a Stored Procedure", 让工作区显示其内容,
然后点击工具栏上的 "Execute" 按钮,如图红框所示:
弹出对话框,如图:
选择数据库,存储过程,存储过程类型,点确定(OK)。
然后可以看到工作区 Output 里输出了代码了。例如:
- using System.Data;
- using System.Collections.Specialized;
- using System.Data.SqlClient;
-
-
-
- public virtual void dm_exec_cursors ( int spid)
- {
- ListDictionary parameters = new ListDictionary();
-
- parameters.Add( new SqlParameter( "@spid" , SqlDbType.Int, 0), spid);
- LoadFromSqlNoExec( "dm_exec_cursors" , parameters);
- }
这就是MyGeneration自动获取了存储过程的输入参数,然后在代码里构造相应的参数,然后生成的代码。
这只是MyGeneration自带的模板生成的,大家可以试一试其他的模板的效果。
里面有自动根据表结构生成BLL的类......看下效果:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- using System;
- using System.Data;
- using System.Data.OleDb;
- using System.Collections;
- using System.Collections.Specialized;
- using MyGeneration.dOOdads;
- namespace Your.Namespace
- {
- public abstract class _Users : OleDbEntity
- {
- public _Users()
- {
- this .QuerySource = "Users" ;
- this .MappingName = "Users" ;
- }
-
-
-
-
-
- public override void AddNew()
- {
- base .AddNew();
-
- }
-
-
- public override string GetAutoKeyColumn()
- {
- return "ID" ;
- }
- public override void FlushData()
- {
- this ._whereClause = null ;
- this ._aggregateClause = null ;
- base .FlushData();
- }
-
-
-
-
-
-
- public bool LoadAll()
- {
- ListDictionary parameters = null ;
-
- return base .LoadFromSql( "[" + this .SchemaStoredProcedure + "proc_UsersLoadAll]" , parameters);
- }
-
-
-
-
-
-
- public virtual bool LoadByPrimaryKey()
- {
- ListDictionary parameters = new ListDictionary();
-
- return base .LoadFromSql( "[" + this .SchemaStoredProcedure + "proc_UsersLoadByPrimaryKey]" , parameters);
- }
-
- #region Parameters
- protected class Parameters
- {
-
- public static OleDbParameter ID
- {
- get
- {
- return new OleDbParameter( "@ID" , OleDbType.Integer, 0);
- }
- }
-
- public static OleDbParameter Alias
- {
- get
- {
- return new OleDbParameter( "@Alias" , OleDbType.VarChar, 2147483647);
- }
- }
-
- }
- #endregion
-
- #region ColumnNames
- public class ColumnNames
- {
- public const string ID = "ID" ;
- public const string Alias = "Alias" ;
- static public string ToPropertyName( string columnName)
- {
- if (ht == null )
- {
- ht = new Hashtable();
-
- ht[ID] = _Users.PropertyNames.ID;
- ht[Alias] = _Users.PropertyNames.Alias;
- }
- return ( string )ht[columnName];
- }
- static private Hashtable ht = null ;
- }
- #endregion
-
- #region PropertyNames
- public class PropertyNames
- {
- public const string ID = "ID" ;
- public const string Alias = "Alias" ;
- static public string ToColumnName( string propertyName)
- {
- if (ht == null )
- {
- ht = new Hashtable();
-
- ht[ID] = _Users.ColumnNames.ID;
- ht[Alias] = _Users.ColumnNames.Alias;
- }
- return ( string )ht[propertyName];
- }
- static private Hashtable ht = null ;
- }
- #endregion
- #region StringPropertyNames
- public class StringPropertyNames
- {
- public const string ID = "s_ID" ;
- public const string Alias = "s_Alias" ;
- }
- #endregion
-
- #region Properties
-
- public virtual Integer ID
- {
- get
- {
- return base .GetInteger(ColumnNames.ID);
- }
- set
- {
- base .SetInteger(ColumnNames.ID, value);
- }
- }
- public virtual String Alias
- {
- get
- {
- return base .GetString(ColumnNames.Alias);
- }
- set
- {
- base .SetString(ColumnNames.Alias, value);
- }
- }
- #endregion
-
- #region String Properties
-
- public virtual string s_ID
- {
- get
- {
- return this .IsColumnNull(ColumnNames.ID) ? string .Empty : base .GetIntegerAsString(ColumnNames.ID);
- }
- set
- {
- if ( string .Empty == value)
- this .SetColumnNull(ColumnNames.ID);
- else
- this .ID = base .SetIntegerAsString(ColumnNames.ID, value);
- }
- }
- public virtual string s_Alias
- {
- get
- {
- return this .IsColumnNull(ColumnNames.Alias) ? string .Empty : base .GetStringAsString(ColumnNames.Alias);
- }
- set
- {
- if ( string .Empty == value)
- this .SetColumnNull(ColumnNames.Alias);
- else
- this .Alias = base .SetStringAsString(ColumnNames.Alias, value);
- }
- }
- #endregion
-
-
- private AggregateClause _aggregateClause = null ;
- #endregion
-
- protected override IDbCommand GetInsertCommand()
- {
-
- OleDbCommand cmd = new OleDbCommand();
- cmd.CommandType = CommandType.StoredProcedure;
- cmd.CommandText = "[" + this .SchemaStoredProcedure + "proc_UsersInsert]" ;
-
- CreateParameters(cmd);
-
- return cmd;
- }
-
- protected override IDbCommand GetUpdateCommand()
- {
-
- OleDbCommand cmd = new OleDbCommand();
- cmd.CommandType = CommandType.StoredProcedure;
- cmd.CommandText = "[" + this .SchemaStoredProcedure + "proc_UsersUpdate]" ;
-
- CreateParameters(cmd);
-
- return cmd;
- }
-
- protected override IDbCommand GetDeleteCommand()
- {
-
- OleDbCommand cmd = new OleDbCommand();
- cmd.CommandType = CommandType.StoredProcedure;
- cmd.CommandText = "[" + this .SchemaStoredProcedure + "proc_UsersDelete]" ;
-
- OleDbParameter p;
-
- return cmd;
- }
-
- private IDbCommand CreateParameters(OleDbCommand cmd)
- {
- OleDbParameter p;
-
- p = cmd.Parameters.Add(Parameters.ID);
- p.SourceColumn = ColumnNames.ID;
- p.SourceVersion = DataRowVersion.Current;
- p = cmd.Parameters.Add(Parameters.Alias);
- p.SourceColumn = ColumnNames.Alias;
- p.SourceVersion = DataRowVersion.Current;
- return cmd;
- }
- }
- }
这就是自动获得表结构,然后从字段映射成类里面的成员,并且还有一些插入,更新,删除的代码。
当然自带的模板生成的代码不一定符合我们的需要,但是我们可以根据需要自己写一些模板来生成符合自己需要的代码,这也是非常容易的事,欲知如何实现,请看下回文章。
===========================================================
要用MyGeneration就必须要和各种模板打交道。我们可以使用别人写的模板来完成我们说需要的功能,但是别人写的模板不一定最适合我们的项目里面的代码,所以有时也需要自己写一些模板来使用。下面就讲如何编写模板吧
通过File – New 菜单我们可以看到,MyGeneration支持的模板包括C#,VB.Net,Jscript,VBScript,我们可以选则自己擅长的语言来写模板。
最简单的办法就是找一个功能差不多的模板,然后在这个模板的基础上进行修改了。这个也是初学的办法,可以快速的了解如何实现特定的功能。
当然,我们要自己建一个模板,以C#模板为例吧。
假如我们要自己生成一个数据库的数据表所对应的BLL类。
在UI界面上需要我们选择是哪个数据库,那张数据表。最后生成BLL类。
选择菜单 File – New – C# Zeus Template,就打开了一个新的工作区,该模板的代码是C#的。工作区有5个Tab页,Template Code, Interface Code, Template Source, Interface Source, Output.如下图所示:
这些都干什么的呢?
这得了解一下MyGeneration内部的结构了。MyGeneration通过脚本引擎执行Template Code和Interface Code中的脚本,生成Template Source和Interface Source的代码,然后执行Interface Source显示用户界面,再执行Template Source,输出结果到Output中。
由此可见,Template Source是根据Template code生成的Interface Source是根据Interface code生成的,他们是不可编辑的。我们能用代码控制的就是Template code和Interface code了。而Interface code是主要和用户界面有关的,Template code则主要控制执行完用户界面的代码后如何输出到Output。
默认生成的Interface Code如下所示:
- public class GeneratedGui : DotNetScriptGui
- {
- public GeneratedGui(ZeusContext context) : base (context) {}
-
-
-
- public override void Setup()
- {
-
-
-
-
-
- }
- }
Interface Code中编写用户界面有两种方法,一种是采用MyGeneration提供的GUI库,另外一种则是完全采用C#本身的界面代码编写。下图显示了MyGeneration的GUI库的帮助,从中可以看到其提供的各种GUI类。
我可不想为了写个模板去学习使用MyGeneration的GUI库,这可加大了学习成本,而且所有界面都得用代码一行一行的写出来,多麻烦啊。如果能像C#那样,直接用鼠标拖拽控件就能搞定界面UI就好了。
其 实,我们是可以用C#的界面库的。我的方法是这样的。先自己用VS新建一个Windows的工程,然后在窗体上摆好控件,设置各种控件的属性,并且把需要 用的各种控件的事件都让VS的IDE生成好。然后把这个窗体的代码直接拷贝到MyGeneration的Interface code里面去。注意,假设我们的窗体叫Form1,我们需要拷贝Form1.Designer.cs 和Form1.cs两个文件中的代码。
然后在Interface Code最前面加入下面两行:
- <%#REFERENCE System.Windows.Forms.dll, System.Drawing.dll %>
- <%#NAMESPACE System.Windows.Forms, System.Drawing %>
在Setup()函数中写:
- Form1 form = new Form1();
- if (form.ShowDialog() != DialogResult.OK)
- {
- ui.IsCanceled = true ;
- }
最后所形成的Interface Code的代码如下所示:
- <%#REFERENCE System.Windows.Forms.dll, System.Drawing.dll %>
- <%#NAMESPACE System.Windows.Forms, System.Drawing %>
- public class GeneratedGui : DotNetScriptGui
- {
- public GeneratedGui(ZeusContext context) : base (context) {}
-
-
-
- public override void Setup()
- {
-
-
-
-
-
- Form1 form = new Form1();
- if (form.ShowDialog() != DialogResult.OK)
- {
- ui.IsCanceled = true ;
- }
- }
- }
- public class Form1:Form
- {
-
-
-
- private System.ComponentModel.IContainer components = null ;
-
-
-
-
- protected override void Dispose( bool disposing)
- {
- if (disposing && (components != null ))
- {
- components.Dispose();
- }
- base .Dispose(disposing);
- }
- #region Windows Form Designer generated code
-
-
-
-
- private void InitializeComponent()
- {
- this .comboBox1 = new System.Windows.Forms.ComboBox();
- this .listBox1 = new System.Windows.Forms.ListBox();
- this .button1 = new System.Windows.Forms.Button();
- this .SuspendLayout();
-
-
-
- this .comboBox1.FormattingEnabled = true ;
- this .comboBox1.Location = new System.Drawing.Point(22, 24);
- this .comboBox1.Name = "comboBox1" ;
- this .comboBox1.Size = new System.Drawing.Size(233, 20);
- this .comboBox1.TabIndex = 0;
- this .comboBox1.SelectedIndexChanged += new System.EventHandler( this .comboBox1_SelectedIndexChanged);
-
-
-
- this .listBox1.FormattingEnabled = true ;
- this .listBox1.ItemHeight = 12;
- this .listBox1.Location = new System.Drawing.Point(22, 50);
- this .listBox1.Name = "listBox1" ;
- this .listBox1.Size = new System.Drawing.Size(233, 196);
- this .listBox1.TabIndex = 1;
-
-
-
- this .button1.Location = new System.Drawing.Point(180, 252);
- this .button1.Name = "button1" ;
- this .button1.Size = new System.Drawing.Size(75, 23);
- this .button1.TabIndex = 2;
- this .button1.Text = "OK" ;
- this .button1.UseVisualStyleBackColor = true ;
-
-
-
- this .AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
- this .AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this .ClientSize = new System.Drawing.Size(284, 293);
- this .Controls.Add( this .button1);
- this .Controls.Add( this .listBox1);
- this .Controls.Add( this .comboBox1);
- this .MaximizeBox = false ;
- this .MinimizeBox = false ;
- this .Name = "Form1" ;
- this .Text = "ZhouKai's BLL Class" ;
- this .Load += new System.EventHandler( this .Form1_Load);
- this .ResumeLayout( false );
- }
- #endregion
- private System.Windows.Forms.ComboBox comboBox1;
- private System.Windows.Forms.ListBox listBox1;
- private System.Windows.Forms.Button button1;
-
-
- public Form1()
- {
- InitializeComponent();
- }
- private void comboBox1_SelectedIndexChanged( object sender, EventArgs e)
- {
- }
- private void Form1_Load( object sender, EventArgs e)
- {
- }
- }
执行一下该模板,看有什么效果吧?是不是看到了如下的UI呢?
呵呵,这个只有UI,还没有数据,下次该讲如何给这个UI加上他说需要的数据啦。比如如何获得数据库的各个数据表啊之内的,然后如何输出自己说需要BLL代码和存储过程的代码啦。
呵呵,发现竟然有网站转载我的文章了,心里小小高兴一下,说明写的东西还是有点用的。
==============================================================
前面讲了MyGeneration的使用,以及如何自己写模板显示UI,现在开始讲如何将数据库的信息显示到UI上。
在MyGeneraion脚本系统中,有一个全局变量,叫做MyMeta,他是dbRoot类型的。通过这个全局变量,我们可以获得数据库相关的信息。这个变量在Interface Code 和Template Code中都可以使用。
从上节代码来看,我们建立Form窗口的时候,就把这个变量给传给了Form窗口
如下代码所示:
MyForm form = new MyForm(MyMeta, input);
那么dbRoot类型的MyMeta变量都有哪些功能,有哪些函数,属性可以使用呢?
我们可以查找帮助,通过MyGeneration菜单 “File – Help – MyMeta API Reference”可以打开其帮助,里面有dbRoot的详细介绍,如下图所示:
大概看一下API,然后我们就可以修改我们的模板了,将其修改如下:
- private void Form1_Load( object sender, EventArgs e)
- {
-
- comboBox1.DataSource = this .myMeta.Databases;
-
- this .comboBox1.DisplayMember = "Name" ;
-
- if ( this .myMeta.DefaultDatabase != null )
- {
-
- this .comboBox1.SelectedIndex = this .comboBox1.FindStringExact( this .myMeta.DefaultDatabase.Name);
-
-
- this .listBox1.DataSource = this .myMeta.DefaultDatabase.Tables;
-
- this .listBox1.DisplayMember = "Name" ;
- }
- }
-
就算没有注释,这代码也很好懂吧。
呵呵,由此可见,我们可以通过MyMeta得到IDataBases,然后获得ITable,在通过ITable
获得数据表的信息……反正呢,照这条线找下去,基本上数据库里有哪些表,表里有哪些字段,有哪些存储过程,任何信息都可以很容易的得到。当然了,在自己写模板之前,最好先大概看一下“MyMeta API Reference”,这样就写模板就会更得心应手了。
下面接下来看Form点击OK之后的代码吧
- private void button1_Click( object sender, EventArgs e)
- {
- IDatabase database = this .comboBox1.SelectedValue as IDatabase;
- ITable table = this .listBox1.SelectedValue as ITable;
-
- this .zeusInput[ "databaseName" ] = database.Name;
- this .zeusInput[ "tableName" ] = table.Name;
-
- this .DialogResult = DialogResult.OK;
- this .Close();
- }
这段代码得重点讲一下了,因为Interface Code是关于UI的,那么UI执行完了之后,我们就需要用到Template Code了,那么Template Code和Interface Code是如何联系在一起的呢? 我们在Template Code里面如何知道Interface Code显示的UI中用户输入了什么,选择了什么?
这用到了MyGeneration的一个非常重要的类IZeusInput。
改接口的详细信息请看帮助 “File – help – Zeus API Reference”。
在这里我们简单的把UI上选中的数据库的名字和数据表的名字存在了IZeusInput变量中。大家注意看下Form的IZeumInput是如何来的吧。
这样,我们就完成了该模板的Interface Code的代码,最后形成的Interface Code就如下所示:
- <%#REFERENCE System.Windows.Forms.dll, System.Drawing.dll %>
- <%#NAMESPACE System.Windows.Forms, System.Drawing %>
- public class GeneratedGui : DotNetScriptGui
- {
- public GeneratedGui(ZeusContext context) : base (context) {}
-
-
-
- public override void Setup()
- {
-
-
-
-
-
- Form1 form = new Form1(MyMeta, input);
- if (form.ShowDialog() != DialogResult.OK)
- {
- ui.IsCanceled = true ;
- }
- }
- }
- public class Form1:Form
- {
-
-
-
- private System.ComponentModel.IContainer components = null ;
-
-
-
-
- protected override void Dispose( bool disposing)
- {
- if (disposing && (components != null ))
- {
- components.Dispose();
- }
- base .Dispose(disposing);
- }
- #region Windows Form Designer generated code
-
-
-
-
- private void InitializeComponent()
- {
- this .comboBox1 = new System.Windows.Forms.ComboBox();
- this .listBox1 = new System.Windows.Forms.ListBox();
- this .button1 = new System.Windows.Forms.Button();
- this .SuspendLayout();
-
-
-
- this .comboBox1.FormattingEnabled = true ;
- this .comboBox1.Location = new System.Drawing.Point(22, 24);
- this .comboBox1.Name = "comboBox1" ;
- this .comboBox1.Size = new System.Drawing.Size(233, 20);
- this .comboBox1.TabIndex = 0;
- this .comboBox1.SelectedIndexChanged += new System.EventHandler( this .comboBox1_SelectedIndexChanged);
-
-
-
- this .listBox1.FormattingEnabled = true ;
- this .listBox1.ItemHeight = 12;
- this .listBox1.Location = new System.Drawing.Point(22, 50);
- this .listBox1.Name = "listBox1" ;
- this .listBox1.Size = new System.Drawing.Size(233, 196);
- this .listBox1.TabIndex = 1;
-
-
-
- this .button1.Location = new System.Drawing.Point(180, 252);
- this .button1.Name = "button1" ;
- this .button1.Size = new System.Drawing.Size(75, 23);
- this .button1.TabIndex = 2;
- this .button1.Text = "OK" ;
- this .button1.UseVisualStyleBackColor = true ;
- this .button1.Click += new System.EventHandler( this .button1_Click);
-
-
-
- this .AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
- this .AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this .ClientSize = new System.Drawing.Size(284, 293);
- this .Controls.Add( this .button1);
- this .Controls.Add( this .listBox1);
- this .Controls.Add( this .comboBox1);
- this .MaximizeBox = false ;
- this .MinimizeBox = false ;
- this .Name = "Form1" ;
- this .Text = "ZhouKai's BLL Class" ;
- this .Load += new System.EventHandler( this .Form1_Load);
- this .ResumeLayout( false );
- }
- #endregion
- private System.Windows.Forms.ComboBox comboBox1;
- private System.Windows.Forms.ListBox listBox1;
- private System.Windows.Forms.Button button1;
-
-
- private dbRoot myMeta;
- private IZeusInput zeusInput;
- public Form1(dbRoot myMeta, IZeusInput zeusInput)
- {
- this .myMeta = myMeta;
- this .zeusInput = zeusInput;
-
- InitializeComponent();
- }
- private void comboBox1_SelectedIndexChanged( object sender, EventArgs e)
- {
- IDatabase database = this .comboBox1.SelectedValue as IDatabase;
- if (database != null )
- {
- this .listBox1.DataSource = database.Tables;
- this .listBox1.DisplayMember = "Name" ;
- }
- }
- private void Form1_Load( object sender, EventArgs e)
- {
-
- comboBox1.DataSource = this .myMeta.Databases;
-
- this .comboBox1.DisplayMember = "Name" ;
-
- if ( this .myMeta.DefaultDatabase != null )
- {
-
- this .comboBox1.SelectedIndex = this .comboBox1.FindStringExact( this .myMeta.DefaultDatabase.Name);
-
-
- this .listBox1.DataSource = this .myMeta.DefaultDatabase.Tables;
-
- this .listBox1.DisplayMember = "Name" ;
- }
- }
-
- private void button1_Click( object sender, EventArgs e)
- {
- IDatabase database = this .comboBox1.SelectedValue as IDatabase;
- ITable table = this .listBox1.SelectedValue as ITable;
-
- this .zeusInput[ "databaseName" ] = database.Name;
- this .zeusInput[ "tableName" ] = table.Name;
-
- this .DialogResult = DialogResult.OK;
- this .Close();
- }
- }
下面来看Template Code如何写吧。目前的模板默认的Template Code如下所示:
- <%
- public class GeneratedTemplate : DotNetScriptTemplate
- {
- public GeneratedTemplate(ZeusContext context) : base (context) {}
-
-
-
- public override void Render()
- {
- %>
- You can toggle in out of script like this
- <%
- output.writeln( "Hello world." );
- }
- }
- %>
C# Template Code的语法和Asp的语法十分的类似<%=%>表示绑定某一个字段或属性
<%%>表示脚本段,我们可以在这里写符合C#语法的任何语句
其他的内容不进行解析直接用output写到最后的结果里
修改Template Code,改成如下所示:
- <%
- public class GeneratedTemplate : DotNetScriptTemplate
- {
- public GeneratedTemplate(ZeusContext context) : base (context) {}
- public override void Render()
- {
-
- MyMeta.Language = "C#" ;
- MyMeta.DbTarget = "SQLClient" ;
-
- string databaseName = input[ "databaseName" ].ToString();
- string tableName = input[ "tableName" ].ToString();
-
- IDatabase database = MyMeta.Databases[databaseName];
-
- ITable table = database.Tables[tableName];
-
- %>
-
- namespace BLL
- {
- using System;
- using System.Data;
-
- using System.Collections;
- using System.Collections.Generic;
-
- <%
-
- output.writeln( " public partial class " + tableName );
- output.writeln( " { " );
-
-
- foreach (IColumn column in table.Columns)
- {
-
- string tmpColumnName = DnpUtils.SetCamelCase(column.Name);
- output.writeln( " private " + column.LanguageType + " _" + tmpColumnName + ";" );
- output.writeln( " public " + column.LanguageType + " " + column.Name);
- output.writeln( " {" );
- output.writeln( " get { return _" + tmpColumnName + "; }" );
- output.writeln( " set { _" + tmpColumnName + " = value; }" );
- output.writeln( " }" );
- output.writeln( "" );
- }
- output.writeln( " } " );
- output.writeln( "}" );
- }
- }
- %>
这代码也非常简单,基本不用解释都能看懂,不用几分钟就能自己写出来了。
运行一下该模板,看下是不是类似有如下输出呢?
- namespace BLL
- {
- using System;
- using System.Data;
-
- public partial class User
- {
- private int _id;
- public int ID
- {
- get { return _id; }
- set { _id = value; }
- }
- private string _userName;
- public string UserName
- {
- get { return _userName; }
- set { _userName = value; }
- }
- }
- }
好了,最简单的一个生成BLL类的模板就完成了。
本来还想写下如何用MyGeneration来生成执行存储过程的函数,如何用MyGeneration来生成测试存储过程函数的代码的。我觉得完成了这个模板,基本上就可以自己查找MyGeneration的帮助中的API完成这些了,应该不用继续下去了。
继续意淫一下,假如写数据库相关的程序,有了MyGeneration,我们的工作就简单多了,我们可以自己写模板,自动生成BLL类,DAL代码,自动生成测试代码……多棒啊
本文来自
http://blog.csdn.net/zxcred
MyGeneration下载地址
http://download.csdn.net/source/1328655