Dbml檔案提取建表TSql-CodeSmith
在昨天一個大學師弟,他問我能不能將LinqToSql檔案轉化為建立表的TSql語句,他是剛開始學習.NET,所以在網上下些示例看,但苦於沒有資料庫。所以就有了這一篇部落格,作為我的Code生成技術的CodeSimth的最後一篇示例。在下一步Code 生成技術將轉到Microsoft的T4模板,Code生成技術目前完成的有CodeDom,CodeSmith模板,高手請不要拍磚,請直接跳過。
在Linq2Sql的Dbml檔案其實就是一個Xml檔案,記錄著資料庫與生成Linq2SqlCode的資料資訊,所以轉化為TSql沒有什麼說的。我們需要提取其中的資料庫資訊,在轉化為我們的Tsql,在這裡建立了DBTable、DBColumn、DBAssociation三個實體類:程式碼
- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.Linq;
- 4 using System.Text;
- 5
- 6 namespace DbmlToTable
- 7 {
- 8 public class DBTable
- 9 {
- 10
- 11 public DBTable()
- 12 {
- 13 Columns = new List<DBColumn>();
- 14 this.Associations = new List<DBAssociation>();
- 15 }
- 16
- 17 public string TableName
- 18 {
- 19 get;
- 20 set;
- 21 }
- 22
- 23 public List<DBColumn> Columns
- 24 {
- 25 get;
- 26 set;
- 27 }
- 28
- 29 public List<DBAssociation> Associations
- 30 {
- 31 get;
- 32 set;
- 33 }
- 34
- 35 }
- 36
- 37 public class DBColumn
- 38 {
- 39 public string Name
- 40 {
- 41 get;
- 42 set;
- 43 }
- 44
- 45 public string DBType
- 46 {
- 47 get;
- 48 set;
- 49 }
- 50
- 51 public bool IsPrimaryKey
- 52 {
- 53 get;
- 54 set;
- 55 }
- 56
- 57 public bool IsDbGenerated
- 58 {
- 59 get;
- 60 set;
- 61 }
- 62
- 63 public bool CanBeNull
- 64 {
- 65 get;
- 66 set;
- 67 }
- 68 }
- 69
- 70 public class DBAssociation
- 71 {
- 72 public string Name
- 73 {
- 74 get;
- 75 set;
- 76 }
- 77
- 78 public string ThisKey
- 79 {
- 80 get;
- 81 set;
- 82 }
- 83
- 84 public string OtherKey
- 85 {
- 86 get;
- 87 set;
- 88 }
- 89
- 90 public bool IsForeignKey
- 91 {
- 92 get;
- 93 set;
- 94 }
- 95 }
- 96
- 97 public class DBTableHlper
- 98 {
- 99 public static DBTable GetAssociationTable(List<DBTable> collection,string assName)
- 100 {
- 101
- 102 return collection.Find(t => t.Associations.Find(a => !a.IsForeignKey && a.Name == assName) != null);
- 103 }
- 104 }
- 105 }
- 106
- 107
- 複製程式碼
其中DBTableHlper是由於我的Codesimth是2.0版本的,不能用lamdam表示式,所以我將它編譯在程式集裡面。
建立了一個 將我們的dbml檔案xml Document轉化為實體類輔助類:
- 程式碼
- 1 using System;
- 2 using System.Collections.Generic;
- 3 using System.Linq;
- 4 using System.Text;
- 5 using System.Xml;
- 6 using System.Xml.Linq;
- 7
- 8 namespace DbmlToTable
- 9 {
- 10
- 11 public interface IDbTableCollectionHelper
- 12 {
- 13 List<DBTable> Transport(XElement element);
- 14 }
- 15
- 16 public class DbTableCollectionHelper : IDbTableCollectionHelper
- 17 {
- 18 #region IDbTableCollectionHelper 成員
- 19
- 20 public List<DBTable> Transport(XElement element)
- 21 {
- 22 List<DBTable> collection = new List<DBTable>();
- 23 var tables = element.Elements(XName.Get("Table", "http://schemas.microsoft.com/linqtosql/dbml/2007%22));
- 24 foreach (var tab in tables)
- 25 {
- 26 DBTable t = new DBTable() { TableName = tab.Attribute("Name").Value };
- 27 var cols = tab.Element(XName.Get("Type", "http://schemas.microsoft.com/linqtosql/dbml/2007%22)).Elements(XName.Get(%22Column%22, "http://schemas.microsoft.com/linqtosql/dbml/2007%22));
- 28 foreach (var col in cols)
- 29 {
- 30 DBColumn c = new DBColumn()
- 31 {
- 32 CanBeNull = col.Attribute("CanBeNull") != null ? col.Attribute("CanBeNull").Value.ToLower() == "true" : false,
- 33 DBType = col.Attribute("DbType") != null ? col.Attribute("DbType").Value : "",
- 34 IsDbGenerated = col.Attribute("IsDbGenerated") != null ? col.Attribute("IsDbGenerated").Value.ToLower() == "true" : false,
- 35 IsPrimaryKey = col.Attribute("IsPrimaryKey") != null ? col.Attribute("IsPrimaryKey").Value.ToLower() == "true" : false,
- 36 Name = col.Attribute("Name") != null ? col.Attribute("Name").Value : ""
- 37 };
- 38 t.Columns.Add(c);
- 39 }
- 40
- 41 var ass = tab.Element(XName.Get("Type", "http://schemas.microsoft.com/linqtosql/dbml/2007%22)).Elements(XName.Get(%22Association%22, "http://schemas.microsoft.com/linqtosql/dbml/2007%22));
- 42 foreach (var item in ass)
- 43 {
- 44 DBAssociation a = new DBAssociation()
- 45 {
- 46 Name = item.Attribute("Name") != null ? item.Attribute("Name").Value : "",
- 47 OtherKey = item.Attribute("OtherKey") != null ? item.Attribute("OtherKey").Value : "",
- 48 ThisKey = item.Attribute("ThisKey") != null ? item.Attribute("ThisKey").Value : "",
- 49 IsForeignKey = item.Attribute("IsForeignKey") != null ? item.Attribute("IsForeignKey").Value.ToLower() == "true" : false
- 50 };
- 51 t.Associations.Add(a);
- 52 }
- 53 collection.Add(t);
- 54 }
- 55 return collection;
- 56 }
- 57
- 58 #endregion
- 59 }
- 60 }
- 61
- 62
- 複製程式碼
在轉化為我們的實體類,我們剩下的就是編寫我們的CodeSmith模板了(更多知識可以參考CodeSmith模板):
- 程式碼
- 1 <%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" Debug="False" Description="Template description here." %>
- 2
- 3 <%@ Import NameSpace="System" %>
- 4 <%@ Import NameSpace="System.Xml" %>
- 5 <%@ Import NameSpace="System.Text" %>
- 6 <%@ Import NameSpace="System.Collections.Generic" %>
- 7 <%@ Assembly Name="DbmlToTable" %>
- 8
- 9 --Code By Wolf
- 10 <script runat="template">
- 11 private List<DbmlToTable.DBTable> _DbTableCollection;
- 12 public List<DbmlToTable.DBTable> DbTableCollection
- 13 {
- 14 get
- 15 {
- 16 return _DbTableCollection;
- 17 }
- 18 set
- 19 {
- 20 _DbTableCollection=value;
- 21 }
- 22 }
- 23
- 24 public string GeneratorTableSql(List<DbmlToTable.DBTable> collection)
- 25 {
- 26 StringBuilder sb = new StringBuilder();
- 27 StringBuilder sbAssocation = new StringBuilder();
- 28 foreach (DbmlToTable.DBTable item in collection)
- 29 {
- 30 List<string> cols = new List<string>();
- 31 foreach (DbmlToTable.DBColumn col in item.Columns)
- 32 {
- 33 cols.Add(string.Format("{0} {1} {2} ", col.Name, col.DBType, col.IsPrimaryKey ? "PRIMARY KEY " : ""));
- 34 }
- 35 sb.AppendFormat("\r\nCREATE TABLE {0} \r\n(\r\n{1}\r\n)", item.TableName, string.Join(",\r\n", cols.ToArray()));
- 36
- 37 foreach (DbmlToTable.DBAssociation ass in item.Associations)
- 38 {
- 39 if (ass.IsForeignKey)
- 40 {
- 41 DbmlToTable.DBTable tab = DbmlToTable.DBTableHlper.GetAssociationTable(collection,ass.Name);
- 42 if (tab != null)
- 43 {
- 44 sbAssocation.AppendLine();
- 45 sbAssocation.AppendFormat(@"ALTER TABLE {0} WITH NOCHECK ADD CONSTRAINT {1} FOREIGN KEY({2}) REFERENCES {3} ({4})",
- 46 item.TableName, "FK_" + ass.Name, ass.ThisKey, tab.TableName, ass.OtherKey);
- 47 }
- 48 }
- 49 }
- 50 }
- 51
- 52 return sb.ToString() + "\r\n" + sbAssocation.ToString();
- 53 }
- 54 </script>
- 55 <%= this.GeneratorTableSql(_DbTableCollection) %>
- 56
- 57
- 複製程式碼
在codeSimth中我們建立了一個集合屬性傳遞實體類DBTable和一個轉化TSql輔助方法.
在控制檯呼叫編譯模板以及輸出:
- 程式碼
- 1 <%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" Debug="False" Description="Template description here." %>
- 2
- 3 <%@ Import NameSpace="System" %>
- 4 <%@ Import NameSpace="System.Xml" %>
- 5 <%@ Import NameSpace="System.Text" %>
- 6 <%@ Import NameSpace="System.Collections.Generic" %>
- 7 <%@ Assembly Name="DbmlToTable" %>
- 8
- 9 --Code By Wolf
- 10 <script runat="template">
- 11 private List<DbmlToTable.DBTable> _DbTableCollection;
- 12 public List<DbmlToTable.DBTable> DbTableCollection
- 13 {
- 14 get
- 15 {
- 16 return _DbTableCollection;
- 17 }
- 18 set
- 19 {
- 20 _DbTableCollection=value;
- 21 }
- 22 }
- 23
- 24 public string GeneratorTableSql(List<DbmlToTable.DBTable> collection)
- 25 {
- 26 StringBuilder sb = new StringBuilder();
- 27 StringBuilder sbAssocation = new StringBuilder();
- 28 foreach (DbmlToTable.DBTable item in collection)
- 29 {
- 30 List<string> cols = new List<string>();
- 31 foreach (DbmlToTable.DBColumn col in item.Columns)
- 32 {
- 33 cols.Add(string.Format("{0} {1} {2} ", col.Name, col.DBType, col.IsPrimaryKey ? "PRIMARY KEY " : ""));
- 34 }
- 35 sb.AppendFormat("\r\nCREATE TABLE {0} \r\n(\r\n{1}\r\n)", item.TableName, string.Join(",\r\n", cols.ToArray()));
- 36
- 37 foreach (DbmlToTable.DBAssociation ass in item.Associations)
- 38 {
- 39 if (ass.IsForeignKey)
- 40 {
- 41 DbmlToTable.DBTable tab = DbmlToTable.DBTableHlper.GetAssociationTable(collection,ass.Name);
- 42 if (tab != null)
- 43 {
- 44 sbAssocation.AppendLine();
- 45 sbAssocation.AppendFormat(@"ALTER TABLE {0} WITH NOCHECK ADD CONSTRAINT {1} FOREIGN KEY({2}) REFERENCES {3} ({4})",
- 46 item.TableName, "FK_" + ass.Name, ass.ThisKey, tab.TableName, ass.OtherKey);
- 47 }
- 48 }
- 49 }
- 50 }
- 51
- 52 return sb.ToString() + "\r\n" + sbAssocation.ToString();
- 53 }
- 54 </script>
- 55 <%= this.GeneratorTableSql(_DbTableCollection) %>
- 56
- 57
- 複製程式碼
在CodeSimth中就是這麼簡單,生成相應的模板程式碼(個人理解CodeSmith就是把程式碼作為字串輸出)。
在上面到我的CodeSmith模板編譯輔助類,在上一篇通過程式碼生成機制實現強型別程式設計-CodeSmith版也有,在這裡也附帶上:需要引用CodeSmith.Engine.dll.
- 程式碼
- 1 using System;
- 2
- 3 using System.Collections.Generic;
- 4
- 5 using System.Linq;
- 6
- 7 using System.Text;
- 8
- 9 using CodeSmith.Engine;
- 10
- 11 using Wolf.NameValueDictionary;
- 12
- 13 namespace DbmlToTable
- 14
- 15 {
- 16
- 17 public class CodeSimthTemplateHelper
- 18
- 19 {
- 20
- 21 public static CodeTemplate CompileTemplate(string templateName, Action errorWriter)
- 22
- 23 {
- 24
- 25 CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateName); compiler.Compile();
- 26
- 27 if (compiler.Errors.Count == 0)
- 28
- 29 {
- 30
- 31 return compiler.CreateInstance();
- 32
- 33 }
- 34
- 35 else
- 36
- 37 {
- 38
- 39 for (int i = 0; i < compiler.Errors.Count; i++)
- 40
- 41 {
- 42
- 43 errorWriter(compiler.Errors[i].ToString());
- 44
- 45 }
- 46
- 47 return null;
- 48
- 49 }
- 50
- 51 }
- 52
- 53
- 54
- 55 public static void AddPropertyParams(CodeTemplate template,object param)
- 56
- 57 {
- 58
- 59 NameValueDictionary dict = new NameValueDictionary<object>(param);
- 60
- 61 AddPropertyParams(template, dict);
- 62
- 63 }
- 64
- 65
- 66
- 67 public static void AddPropertyParams(CodeTemplate template, NameValueDictionary<object> param)
- 68
- 69 {
- 70
- 71 NameValueDictionary<object> dict = new NameValueDictionary<object>(param);
- 72
- 73 foreach (var item in dict.Keys)
- 74
- 75 {
- 76
- 77 template.SetProperty(item, dict[item]);
- 78
- 79 }
- 80
- 81 }
- 82
- 83 }
- 84
- 85 }
- 86
- 複製程式碼
本文轉自 破狼 51CTO部落格,原文連結:http://blog.51cto.com/whitewolfblog/834728,如需轉載請自行聯絡原作者
相關文章
- !!!提取檔案記錄!!!
- 提取檔名字到excel表中Excel
- 製作ISO檔案 與 提取ISO檔案
- CAB歸檔檔案提取工具cabextract
- File Juicer for Mac(檔案提取工具)UIMac
- nmap掃描檔案提取工具
- 從配置檔案中提取IP
- 提取rpm檔案內容
- 12c 資料泵提取建表空間語句和建表語句
- php檔案操作之提取檔案/目錄的名稱PHP
- 使用os.walk提取壓縮檔案並避免遞迴提取遞迴
- 流量中提取檔案的若干種方法
- 如何使用htmlq提取html檔案內容HTML
- 提取Windows使用者金鑰檔案cachedumpWindows
- 怎麼從系統光碟中提取檔案!
- 沒有目錄建目錄,沒有檔案建檔案
- Oracle從dump檔案中提取DDL語句方法Oracle
- WGET——LINUX下WEB檔案提取工具(轉)wgetLinuxWeb
- Python提取文字檔案(.txt)資料的方法Python
- PostgreSQL的表檔案以及TOAST表檔案對應關係SQLAST
- 手工建庫---控制檔案
- 如何從 dump 檔案中提取出 C# 原始碼?C#原始碼
- 如何用Python從PDF檔案中提取文字詞彙Python
- 去掉字串中重複部分 提取檔案字尾名字串
- File Juicer mac 4.99 中文版 檔案提取工具UIMac
- Python批量提取Word檔案題庫中的答案Python
- git小技巧--提取/合併某分支的部分檔案Git
- 【加密演算法】PFX檔案提取公鑰私鑰加密演算法
- 安卓實用小技巧:將App提取為Apk檔案安卓APPAPK
- 由pcap檔案提取IPv6的flow資料PCA
- AMDU 從頭部損壞的磁碟中提取檔案
- 基於常量值提取淺析elf檔案結構
- 表的schema 檔案
- 移動資料檔案、系統表空間檔案、臨時表空間檔案
- 檔案管理系統助力檔案資訊化建設
- 【巴山】Asp.NET大檔案上傳元件開發總結(二)---提取檔案內容ASP.NET元件
- Oracle 從Dump 檔案裡提取 DDL 語句 方法說明Oracle
- 根檔案系統構建