在昨天一个大学师弟,他问我能不能将LinqToSql文件转化为创建表的TSql语句,他是刚开始学习.NET,所以在网上下些示例看,但苦于没有数据库。所以就有了这一篇博客,作为我的Code生成技术的CodeSimth的最后一篇示例。在下一步Code 生成技术将转到Microsoft的T4模板,Code生成技术目前完成的有CodeDom,CodeSmith模板,高手请不要拍砖,请直接跳过。
在Linq2Sql的Dbml文件其实就是一个Xml文件,记录着数据库与生成Linq2SqlCode的数据信息,所以转化为TSql没有什么说的。我们需要提取其中的数据库信息,在转化为我们的Tsql,在这里建立了DBTable、DBColumn、DBAssociation三个实体类:代码
1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Linq; 4usingSystem.Text; 5 6namespaceDbmlToTable 7{ 8publicclassDBTable 9{ 10 11publicDBTable() 12{ 13Columns=newList<DBColumn>(); 14this.Associations=newList<DBAssociation>(); 15} 16 17publicstringTableName 18{ 19get; 20set; 21} 22 23publicList<DBColumn>Columns 24{ 25get; 26set; 27} 28 29publicList<DBAssociation>Associations 30{ 31get; 32set; 33} 34 35} 36 37publicclassDBColumn 38{ 39publicstringName 40{ 41get; 42set; 43} 44 45publicstringDBType 46{ 47get; 48set; 49} 50 51publicboolIsPrimaryKey 52{ 53get; 54set; 55} 56 57publicboolIsDbGenerated 58{ 59get; 60set; 61} 62 63publicboolCanBeNull 64{ 65get; 66set; 67} 68} 69 70publicclassDBAssociation 71{ 72publicstringName 73{ 74get; 75set; 76} 77 78publicstringThisKey 79{ 80get; 81set; 82} 83 84publicstringOtherKey 85{ 86get; 87set; 88} 89 90publicboolIsForeignKey 91{ 92get; 93set; 94} 95} 96 97publicclassDBTableHlper 98{ 99publicstaticDBTableGetAssociationTable(List<DBTable>collection,stringassName) 100{ 101 102returncollection.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转化为实体类辅助类:
代码 1usingSystem; 2usingSystem.Collections.Generic; 3usingSystem.Linq; 4usingSystem.Text; 5usingSystem.Xml; 6usingSystem.Xml.Linq; 7 8namespaceDbmlToTable 9{ 10 11publicinterfaceIDbTableCollectionHelper 12{ 13List<DBTable>Transport(XElementelement); 14} 15 16publicclassDbTableCollectionHelper:IDbTableCollectionHelper 17{ 18#regionIDbTableCollectionHelper成员 19 20publicList<DBTable>Transport(XElementelement) 21{ 22List<DBTable>collection=newList<DBTable>(); 23vartables=element.Elements(XName.Get("Table","/linqtosql/dbml/%22)); 24foreach(vartabintables) 25{ 26DBTablet=newDBTable(){TableName=tab.Attribute("Name").Value}; 27varcols=tab.Element(XName.Get("Type","/linqtosql/dbml/%22)).Elements(XName.Get(%22Column%22,"/linqtosql/dbml/%22)); 28foreach(varcolincols) 29{ 30DBColumnc=newDBColumn() 31{ 32CanBeNull=col.Attribute("CanBeNull")!=null?col.Attribute("CanBeNull").Value.ToLower()=="true":false, 33DBType=col.Attribute("DbType")!=null?col.Attribute("DbType").Value:"", 34IsDbGenerated=col.Attribute("IsDbGenerated")!=null?col.Attribute("IsDbGenerated").Value.ToLower()=="true":false, 35IsPrimaryKey=col.Attribute("IsPrimaryKey")!=null?col.Attribute("IsPrimaryKey").Value.ToLower()=="true":false, 36Name=col.Attribute("Name")!=null?col.Attribute("Name").Value:"" 37}; 38t.Columns.Add(c); 39} 40 41varass=tab.Element(XName.Get("Type","/linqtosql/dbml/%22)).Elements(XName.Get(%22Association%22,"/linqtosql/dbml/%22)); 42foreach(variteminass) 43{ 44DBAssociationa=newDBAssociation() 45{ 46Name=item.Attribute("Name")!=null?item.Attribute("Name").Value:"", 47OtherKey=item.Attribute("OtherKey")!=null?item.Attribute("OtherKey").Value:"", 48ThisKey=item.Attribute("ThisKey")!=null?item.Attribute("ThisKey").Value:"", 49IsForeignKey=item.Attribute("IsForeignKey")!=null?item.Attribute("IsForeignKey").Value.ToLower()=="true":false 50}; 51t.Associations.Add(a); 52} 53collection.Add(t); 54} 55returncollection; 56} 57 58#endregion 59} 60} 61 62 复制代码
在转化为我们的实体类,我们剩下的就是编写我们的CodeSmith模板了(更多知识可以参考CodeSmith模板):
代码 1<%@CodeTemplateLanguage="C#"TargetLanguage="Text"Src=""Inherits=""Debug="False"Description="Templatedescriptionhere."%> 2 3<%@ImportNameSpace="System"%> 4<%@ImportNameSpace="System.Xml"%> 5<%@ImportNameSpace="System.Text"%> 6<%@ImportNameSpace="System.Collections.Generic"%> 7<%@AssemblyName="DbmlToTable"%> 8 9--CodeByWolf 10<scriptrunat="template"> 11privateList<DbmlToTable.DBTable>_DbTableCollection; 12publicList<DbmlToTable.DBTable>DbTableCollection 13{ 14get 15{ 16return_DbTableCollection; 17} 18set 19{ 20_DbTableCollection=value; 21} 22} 23 24publicstringGeneratorTableSql(List<DbmlToTable.DBTable>collection) 25{ 26StringBuildersb=newStringBuilder(); 27StringBuildersbAssocation=newStringBuilder(); 28foreach(DbmlToTable.DBTableitemincollection) 29{ 30List<string>cols=newList<string>(); 31foreach(DbmlToTable.DBColumncolinitem.Columns) 32{ 33cols.Add(string.Format("{0}{1}{2}",col.Name,col.DBType,col.IsPrimaryKey?"PRIMARYKEY":"")); 34} 35sb.AppendFormat("\r\nCREATETABLE{0}\r\n(\r\n{1}\r\n)",item.TableName,string.Join(",\r\n",cols.ToArray())); 36 37foreach(DbmlToTable.DBAssociationassinitem.Associations) 38{ 39if(ass.IsForeignKey) 40{ 41DbmlToTable.DBTabletab=DbmlToTable.DBTableHlper.GetAssociationTable(collection,ass.Name); 42if(tab!=null) 43{ 44sbAssocation.AppendLine(); 45sbAssocation.AppendFormat(@"ALTERTABLE{0}WITHNOCHECKADDCONSTRAINT{1}FOREIGNKEY({2})REFERENCES{3}({4})", 46item.TableName,"FK_"+ass.Name,ass.ThisKey,tab.TableName,ass.OtherKey); 47} 48} 49} 50} 51 52returnsb.ToString()+"\r\n"+sbAssocation.ToString(); 53} 54</script> 55<%=this.GeneratorTableSql(_DbTableCollection)%> 56 57 复制代码
在codeSimth中我们建立了一个集合属性传递实体类DBTable和一个转化TSql辅助方法.
在控制台调用编译模板以及输出:
代码 1<%@CodeTemplateLanguage="C#"TargetLanguage="Text"Src=""Inherits=""Debug="False"Description="Templatedescriptionhere."%> 2 3<%@ImportNameSpace="System"%> 4<%@ImportNameSpace="System.Xml"%> 5<%@ImportNameSpace="System.Text"%> 6<%@ImportNameSpace="System.Collections.Generic"%> 7<%@AssemblyName="DbmlToTable"%> 8 9--CodeByWolf 10<scriptrunat="template"> 11privateList<DbmlToTable.DBTable>_DbTableCollection; 12publicList<DbmlToTable.DBTable>DbTableCollection 13{ 14get 15{ 16return_DbTableCollection; 17} 18set 19{ 20_DbTableCollection=value; 21} 22} 23 24publicstringGeneratorTableSql(List<DbmlToTable.DBTable>collection) 25{ 26StringBuildersb=newStringBuilder(); 27StringBuildersbAssocation=newStringBuilder(); 28foreach(DbmlToTable.DBTableitemincollection) 29{ 30List<string>cols=newList<string>(); 31foreach(DbmlToTable.DBColumncolinitem.Columns) 32{ 33cols.Add(string.Format("{0}{1}{2}",col.Name,col.DBType,col.IsPrimaryKey?"PRIMARYKEY":"")); 34} 35sb.AppendFormat("\r\nCREATETABLE{0}\r\n(\r\n{1}\r\n)",item.TableName,string.Join(",\r\n",cols.ToArray())); 36 37foreach(DbmlToTable.DBAssociationassinitem.Associations) 38{ 39if(ass.IsForeignKey) 40{ 41DbmlToTable.DBTabletab=DbmlToTable.DBTableHlper.GetAssociationTable(collection,ass.Name); 42if(tab!=null) 43{ 44sbAssocation.AppendLine(); 45sbAssocation.AppendFormat(@"ALTERTABLE{0}WITHNOCHECKADDCONSTRAINT{1}FOREIGNKEY({2})REFERENCES{3}({4})", 46item.TableName,"FK_"+ass.Name,ass.ThisKey,tab.TableName,ass.OtherKey); 47} 48} 49} 50} 51 52returnsb.ToString()+"\r\n"+sbAssocation.ToString(); 53} 54</script> 55<%=this.GeneratorTableSql(_DbTableCollection)%> 56 57 复制代码
在CodeSimth中就是这么简单,生成相应的模板代码(个人理解CodeSmith就是把代码作为字符串输出)。
在上面到我的CodeSmith模板编译辅助类,在上一篇通过代码生成机制实现强类型编程-CodeSmith版也有,在这里也附带上:需要引用CodeSmith.Engine.dll.
代码 1usingSystem; 2 3usingSystem.Collections.Generic; 4 5usingSystem.Linq; 6 7usingSystem.Text; 8 9usingCodeSmith.Engine; 10 11usingWolf.NameValueDictionary; 12 13namespaceDbmlToTable 14 15{ 16 17publicclassCodeSimthTemplateHelper 18 19{ 20 21publicstaticCodeTemplateCompileTemplate(stringtemplateName,ActionerrorWriter) 22 23{ 24 25CodeTemplateCompilercompiler=newCodeTemplateCompiler(templateName);pile(); 26 27if(compiler.Errors.Count==0) 28 29{ 30 31returncompiler.CreateInstance(); 32 33} 34 35else 36 37{ 38 39for(inti=0;i<compiler.Errors.Count;i++) 40 41{ 42 43errorWriter(compiler.Errors[i].ToString()); 44 45} 46 47returnnull; 48 49} 50 51} 52 53 54 55publicstaticvoidAddPropertyParams(CodeTemplatetemplate,objectparam) 56 57{ 58 59NameValueDictionarydict=newNameValueDictionary<object>(param); 60 61AddPropertyParams(template,dict); 62 63} 64 65 66 67publicstaticvoidAddPropertyParams(CodeTemplatetemplate,NameValueDictionary<object>param) 68 69{ 70 71NameValueDictionary<object>dict=newNameValueDictionary<object>(param); 72 73foreach(varitemindict.Keys) 74 75{ 76 77template.SetProperty(item,dict[item]); 78 79} 80 81} 82 83} 84 85} 86 复制代码
本文转自 破狼 51CTO博客,原文链接:/whitewolfblog/834728,如需转载请自行联系原作者
如果觉得《Dbml文件提取建表TSql-CodeSmith》对你有帮助,请点赞、收藏,并留下你的观点哦!