一个实体生成器

  在开发基于三层架构的项目初期,都会按照数据库的表结构定义一堆的实体类,但是一个表里有那么多的字段,一个库又有那么多个表,建这些实体类的工作量不少,作为一个懒人,肯定想些法子解决这么麻烦的问题。写一个实体生成器。

  为了生成器能兼容各仲类型的数据库,我把生成器的架构定义成如下形式

一个实体生成器

  还是说明一下吧!在数据库的上一层定义了各种数据的Controler,负责建立各种数据的连接等等,在DAL的每一个类都实现IDAL接口,每一种数据库的DAL类都定义了各自查询SQL,在BLL处通过读取配置,获知当前需要对哪个类型的数据库操作,再通过反射机制动态生成相应的DAL实例。这样如果再有新的数据库类型,只要添加新的Controler类和新的DAL类,在配置中改一下就行了。

看一下程序的界面

一个实体生成器

项目的结构

一个实体生成器

  Entitiy目录下的是本项目中需要的一些实体类,包括储存表信息的TableENT,列信息的ColumnENT,实体类文件信息的CSFileENT。此生成器生成的类文件并不是通过模板文件来构造文件内容的,文件信息是通过配置文件来配置的,用EntityFileConfig.xml来配置。

   生成实体类的时候要知道数据库里有什么表,表里头有什么字段,相关的SQL语句我只有SQL Server的,其他的数据库还没搞(或者有需要的时候才去搞,呵呵),所以这里暂时只能生成SQL Server的。

下面则各个类的代码,DBC里面的就不展示了,

首先是IDAL接口的,实现IDAL接口的类要实现4个方法,GetTableNames获取数据库表的名称,GetTableInfo根据表的名称获取表的字段信息,ConvertType把数据库的数据类型转换成.NET Framework的类型。

 1     public interface IDAL

 2     {

 3         List<TableENT> GetTabelNames( );

 4 

 5         List<ColumnENT> GetTabelInfo(string tableName);

 6 

 7         string ConvertType(string DbTypeName);

 8 

 9         bool TestConnect();

10     }

到MSSQLDAL

 1     public class MSSQLDAL:IDAL

 2     {

 3         public List<TableENT> GetTabelNames( )

 4         {

 5             List<TableENT> list = new List<TableENT>();

 6             MSSQLControler db = new MSSQLControler();

 7             string cmdText = "SELECT name FROM sysobjects WHERE type='U' ";

 8             DataTable table = db.GetDataTable(cmdText, null);

 9 

10             TableENT ent = null;

11             foreach (DataRow  row in table.Rows)

12             {

13                 ent = new TableENT();

14                 ent.TableName = row["name"]==DBNull.Value?string.Empty:row["name"].ToString();

15                 ent.State = StateEnum.Ready;

16                 list.Add(ent);

17             }

18 

19             return list;

20         }

21 

22         public List<ColumnENT> GetTabelInfo(string tableName)

23         {

24             List<ColumnENT> list = new List<ColumnENT>();

25 

26             MSSQLControler db = new MSSQLControler();

27             string cmdText = "sp_columns @TabelName ";

28             SqlParameter[] paraArr = new SqlParameter[] { new SqlParameter("@TabelName",tableName) };

29             DataTable table = db.GetDataTable(cmdText, paraArr);

30 

31             ColumnENT ent = null;

32             foreach (DataRow row in table.Rows)

33             {

34                 ent = new ColumnENT();

35                 ent.ColumnName = row["COLUMN_NAME"] == DBNull.Value ? string.Empty : row["COLUMN_NAME"].ToString();

36                 ent.DBTypeName = row["TYPE_NAME"] == DBNull.Value ? string.Empty : row["TYPE_NAME"].ToString();

37                 list.Add(ent);

38             }

39             return list;

40         }

41 

42         //分割类型名 

43         public string ConvertType(string DbTypeName)

44         {

45             switch (DbTypeName)

46             {

47                 case "bigint": return "Int64";

48                 case "datetimeoffset": return "DateTimeOffset";

49                 case "float": return "Double";

50                 case "int": return "Int32";

51                 case "real": return "Single";

52                 case "smallint": return "Int16";

53                 case "time": return "TimeSpan";

54                 case "uniqueidentifier": return "Guid";

55                 case "xml": return "Xml";

56                 case "bit": return "Boolean";

57                 case "tinyint": return "Byte";

58             }

59             if (DbTypeName == "char" ||

60                 DbTypeName == "nchar" ||

61                 DbTypeName == "ntext" ||

62                 DbTypeName == "nvarchar" ||

63                 DbTypeName == "text" ||

64                 DbTypeName == "varchar") return "String";

65 

66             if (DbTypeName == "FILESTREAM" ||

67                 DbTypeName == "binary" ||

68                 DbTypeName == "timestamp" ||

69                 DbTypeName == "image" ||

70                 DbTypeName == "rowversion" ||

71                 DbTypeName == "varbinary") return "Byte[]";

72 

73             if (DbTypeName == "datetime" ||

74                 DbTypeName == "date" ||

75                 DbTypeName == "datetime2" ||

76                 DbTypeName == "smalldatetime") return "DateTime";

77 

78 

79             if (DbTypeName == "decimal" ||

80                 DbTypeName == "money" ||

81                 DbTypeName == "numeric" ||

82                 DbTypeName == "smallmoney") return "Decimal";

83 

84             return "object";

85         }

86 

87         public bool TestConnect()

88         {

89             MSSQLControler db = new MSSQLControler();

90             return db.TestConnect();

91         }

92     }

到DbBLL,DbBLL是直接给窗体的事件方法调用的,

 1    public class DbBLL

 2     {

 3         private static string typeName = ConfigurationManager.AppSettings["TypeName"];

 4 

 5         private static string dllPath = ConfigurationManager.AppSettings["dllPath"];

 6 

 7         public List<TableENT> GetTabelNames( )

 8         {

 9             List<TableENT> list = new List<TableENT>();

10             IDAL dal = CreateDAL();

11             if (dal != null) list = dal.GetTabelNames();

12             return list;

13         }

14 

15         public bool CreateEntity(string TableName,string outPath)

16         {

17             IDAL dal = CreateDAL();

18             FileCommon fileBLL = new FileCommon();

19             if (dal == null) return false;

20             List<ColumnENT> colLlist = dal.GetTabelInfo(TableName);

21 

22             CSFileENT file = fileBLL.LoadModelFile();

23             foreach (ColumnENT item in colLlist)

24             {

25                 string colTemp = item.DBTypeName.Split().FirstOrDefault();

26                 item.EntTypeName = dal.ConvertType(colTemp);

27             }

28             file.ClassName = TableName;

29             string content = fileBLL.CreateFileContent(file, colLlist);

30 

31             bool result = false;

32             outPath = outPath.Trim('\\')+"\\" + TableName + "_ENT.cs";

33             result = fileBLL.OutputFile(content,outPath);

34             return result;

35         }

36 

37         public bool TestConnect()

38         {

39             bool result=false;

40             IDAL dal = CreateDAL();

41             if (dal != null) result = dal.TestConnect();

42             return result;

43         }

44 

45         private IDAL CreateDAL()

46         {

47             if (string.IsNullOrEmpty(typeName))

48                 throw new Exception("配置文件里的TypeName不存在或为空");

49             Assembly assembly;

50             if(string.IsNullOrEmpty(dllPath))assembly=Assembly.GetExecutingAssembly();

51             else assembly= Assembly.LoadFile("");

52             Type dalType = assembly.GetType(typeName);

53             IDAL typeIns =assembly.CreateInstance(typeName) as IDAL;

54             return typeIns;

55         }

56     }

FileCommon是生成代码的以及生成实体类文件的类

 1     public class FileCommon

 2     {

 3         public CSFileENT LoadModelFile( )

 4         {

 5             CSFileENT ent = new CSFileENT();

 6             XmlDocument config = new XmlDocument();

 7             config.Load("EntityFileConfig.xml");

 8             XmlNodeList nodeList = config.ChildNodes[1].ChildNodes;

 9             foreach (XmlNode node in nodeList)

10             {

11                 switch (node.Name)

12                 {

13                     case "using":

14                         XmlNodeList usingList = node.ChildNodes;

15                         foreach (XmlNode child in usingList)

16                         {

17                             ent.UsingText += "using " + child.Attributes["value"].Value + ";\r\n";

18                         }

19                         break;

20                     case "namespace":

21                         ent.NameSpaceText = node.Attributes["value"].Value;

22                         break;

23                     case "expand":

24                         XmlNodeList expandList = node.ChildNodes;

25                         foreach (XmlNode child in expandList)

26                         {

27                             ent.Expand += child.Attributes["value"].Value + ",";

28                         }

29                         ent.Expand=ent.Expand.Trim(',');

30                         break;

31                     case "fieldAttribute":

32                         ent.FieldAttribute = node.Attributes["value"].Value;

33                         break;

34                     case "classAttribute":

35                         ent.ClassAttribute = node.Attributes["value"].Value;

36                         break;

37                 }

38             }

39             return ent;

40         }

41 

42         public string CreateFileContent(CSFileENT file, List<ColumnENT> colList)

43         {

44             string result = string.Empty;

45 

46             result += file.UsingText+"{0}";

47             if (!string.IsNullOrEmpty(file.NameSpaceText))

48                 result = string.Format(result, "\r\nnamespace " + file.NameSpaceText + "\r\n{\r\n\t $$ \r\n}").Replace("$$","{0}");

49             result= result.Replace("{0}",file.ClassAttribute + "\r\n\tpublic class " + file.ClassName+"{0}");

50             if (!string.IsNullOrEmpty(file.Expand))

51                 result =result.Replace("{0}", ":"+file.Expand+"{0}");

52             result =result.Replace("{0}", "\r\n\t{\r\n\t\t{0}\r\n\t}");

53 

54             foreach (ColumnENT col in colList)

55             {

56                 string fildText = string.Empty;

57                 if (!string.IsNullOrEmpty(file.FieldAttribute))

58                     fildText += file.FieldAttribute + "\r\n\t\t";

59                 fildText += "public " + col.EntTypeName + " " + col.ColumnName;

60                 result = result.Replace("{0}", fildText + " {get;set;}\r\n\r\n\t\t{0}");

61             }

62 

63             result = result.Replace("{0}","");

64 

65             return result;

66         }

67 

68         public bool OutputFile(string context,string outputPath)

69         {

70             bool result = false;

71 

72             try

73             {

74                 File.WriteAllText(outputPath, context);

75                 result=true;

76             }

77             catch { result = false; }

78             return result;

79         }

80     }

界面的代码就不列举了,接下来到介绍程序的配置

生成实体类的配置

 1 <entityConfig>

 2   <using>

 3     <add value="System" />

 4   </using>

 5   <namespace value="ENT"/>

 6   <expand>

 7     <add value=""/>

 8   </expand>

 9   <fieldAttribute value=""/>

10   <classAttribute value=""/>

11 </entityConfig>

using填的是要引用到的命名空间,namespace是生成类的命名空间的名字,expand是生成类要继承的类和实现的接口的列表,fieldAttribute是字段的Attribute值,classAttribute是类的Attribute,这两个Attribute在WCF方面有用的。

程序配置

1 <configuration>

2   <appSettings>

3     <add key="connectionstring" value="Data Source=localhost\SQLEXPRESS;Initial Catalog=HOMEMAKINGSYSTEM;Integrated Security=true;"/>

4     <add key="TypeName" value="EntityCreator.DAL.MSSQLDAL"/><!--SQL Server:EntityCreator.DAL.MSSQLDAL -->

5     <add key="dllPath" value=""/>

6   </appSettings>

7 

8 </configuration>

connectionstring不用说了;TypeName是当前要调用那个DAL类的完全限定名;若添加了新类型的数据库,可以把新的DAL和Controler类编译成dll,然后把dll的路径放到dllPath里,程序则会生成相应的实例了。

 

经各位过路大侠们指教才发现原来有codesmith这么一个好东西,鄙人真是孤陋寡闻了。

补充两篇博文,是写这个生成器前的准备知识 《各种数据库查询表及表信息的SQL》和《各种数据库与.NET Framework类型对照

你可能感兴趣的:(生成)