Dbml文件提取建表TSql-CodeSmith

2024-01-02 01:32

本文主要是介绍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 using System; 
 2 using System.Collections.Generic; 
 3 using System.Linq; 
 4 using System.Text; 
 5 
 6 namespace DbmlToTable 
 7 { 
 8     class Program 
 9     { 
10         static void Main(string[] args) 
11         { 
12             IDbTableCollectionHelper helper = new DbTableCollectionHelper(); 
13             List<DBTable> collection = helper. 
14                 Transport(System.Xml.Linq.XElement.
15 
16          Load(@"xxpath\MultipleDocument.Data\MultipleDocumentDB.dbml")); 
17 
18             CodeSmith.Engine.CodeTemplate template = CodeSimthTemplateHelper. 
19                 CompileTemplate(@"DBMLToTable.cst", w => Console.WriteLine(w)); 
20             if (template != null) 
21             { 
22                 CodeSimthTemplateHelper.AddPropertyParams(template, new { DbTableCollection = collection }); 
23                 string str = template.RenderToString(); 
24                 Console.WriteLine(str); 
25                 //System.IO.File.AppendAllText(@"D:\1.sql", str); 
26             } 
27             Console.Read(); 
28         }
29 
30 }
31 
32  
33 
34 

复制代码

   在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 

复制代码

这篇关于Dbml文件提取建表TSql-CodeSmith的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/561008

相关文章

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

Python 字符串裁切与提取全面且实用的解决方案

《Python字符串裁切与提取全面且实用的解决方案》本文梳理了Python字符串处理方法,涵盖基础切片、split/partition分割、正则匹配及结构化数据解析(如BeautifulSoup、j... 目录python 字符串裁切与提取的完整指南 基础切片方法1. 使用切片操作符[start:end]2

使用Python提取PDF大纲(书签)的完整指南

《使用Python提取PDF大纲(书签)的完整指南》PDF大纲(Outline)​​是PDF文档中的导航结构,通常显示在阅读器的侧边栏中,方便用户快速跳转到文档的不同部分,大纲通常以层级结构组织,包含... 目录一、PDF大纲简介二、准备工作所需工具常见安装问题三、代码实现完整代码核心功能解析四、使用效果控

Linux从文件中提取特定内容的实用技巧分享

《Linux从文件中提取特定内容的实用技巧分享》在日常数据处理和配置文件管理中,我们经常需要从大型文件中提取特定内容,本文介绍的提取特定行技术正是这些高级操作的基础,以提取含有1的简单需求为例,我们可... 目录引言1、方法一:使用 grep 命令1.1 grep 命令基础1.2 命令详解1.3 高级用法2

Oracle查询表结构建表语句索引等方式

《Oracle查询表结构建表语句索引等方式》使用USER_TAB_COLUMNS查询表结构可避免系统隐藏字段(如LISTUSER的CLOB与VARCHAR2同名字段),这些字段可能为dbms_lob.... 目录oracle查询表结构建表语句索引1.用“USER_TAB_COLUMNS”查询表结构2.用“a

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库

Python中提取文件名扩展名的多种方法实现

《Python中提取文件名扩展名的多种方法实现》在Python编程中,经常会遇到需要从文件名中提取扩展名的场景,Python提供了多种方法来实现这一功能,不同方法适用于不同的场景和需求,包括os.pa... 目录技术背景实现步骤方法一:使用os.path.splitext方法二:使用pathlib模块方法三

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取