一個實體生成器


  在開發基於三層架構的項目初期,都會按照數據庫的表結構定義一堆的實體類,但是一個表里有那么多的字段,一個庫又有那么多個表,建這些實體類的工作量不少,作為一個懶人,肯定想些法子解決這么麻煩的問題。寫一個實體生成器。

  為了生成器能兼容各仲類型的數據庫,我把生成器的架構定義成如下形式

  還是說明一下吧!在數據庫的上一層定義了各種數據的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類型對照


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM