Dbml文件提取建表TSql-CodeSmith

本文介绍如何将LinqToSql的Dbml文件转换为创建表的TSql语句,包括解析Dbml文件获取数据库信息,并利用CodeSmith模板生成对应的TSql脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     在昨天一个大学师弟,他问我能不能将LinqToSql文件转化为创建表的TSql语句,他是刚开始学习.NET,所以在网上下些示例看,但苦于没有数据库。所以就有了这一篇博客,作为我的Code生成技术的CodeSimth的最后一篇示例。在下一步Code 生成技术将转到Microsoft的T4模板,Code生成技术目前完成的有CodeDom,CodeSmith模板,高手请不要拍砖,请直接跳过。

     在Linq2Sql的Dbml文件其实就是一个Xml文件,记录着数据库与生成Linq2SqlCode的数据信息,所以转化为TSql没有什么说的。我们需要提取其中的数据库信息,在转化为我们的Tsql,在这里建立了DBTable、DBColumn、DBAssociation三个实体类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DbmlToTable
{
    public class DBTable
    {

        public DBTable()
        {
            Columns = new List ();
            this.Associations = new List ();
        }

        public string TableName
        {
            get;
            set;
        }

        public List Columns
        {
            get;
            set;
        }

        public List Associations
        {
            get;
            set;
        }

    }

    public class DBColumn
    {
        public string Name
        {
            get;
            set;
        }

        public string DBType
        {
            get;
            set;
        }

        public bool IsPrimaryKey
        {
            get;
            set;
        }

        public bool IsDbGenerated
        {
            get;
            set;
        }

        public bool CanBeNull
        {
            get;
            set;
        }
    }

    public class DBAssociation
    {
        public string Name
        {
            get;
            set;
        }

        public string ThisKey
        {
            get;
            set;
        }

        public string OtherKey
        {
            get;
            set;
        }

        public bool IsForeignKey
        {
            get;
            set;
        }
    }

    public class DBTableHlper
    {
        public static DBTable GetAssociationTable(List collection,string assName)
        {

            return collection.Find(t => t.Associations.Find(a => !a.IsForeignKey && a.Name == assName) != null);
        }
    }
}

    其中DBTableHlper是由于我的Codesimth是2.0版本的,不能用lamdam表达式,所以我将它编译在程序集里面。

   建立了一个 将我们的dbml文件xml Document转化为实体类辅助类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace DbmlToTable
{

    public interface IDbTableCollectionHelper
    {
        List Transport(XElement element);
    }

    public class DbTableCollectionHelper : IDbTableCollectionHelper
    {
        #region IDbTableCollectionHelper 成员

        public List Transport(XElement element)
        {
            List collection = new List ();
            var tables = element.Elements(XName.Get("Table", " http://schemas.microsoft.com/linqtosql/dbml/2007"));
            foreach (var tab in tables)
            {
                DBTable t = new DBTable() { TableName = tab.Attribute("Name").Value };
                var cols = tab.Element(XName.Get("Type", " http://schemas.microsoft.com/linqtosql/dbml/2007")).Elements(XName.Get("Column", " http://schemas.microsoft.com/linqtosql/dbml/2007"));
                foreach (var col in cols)
                {
                    DBColumn c = new DBColumn()
                    {
                        CanBeNull = col.Attribute("CanBeNull") != null ? col.Attribute("CanBeNull").Value.ToLower() == "true" : false,
                        DBType = col.Attribute("DbType") != null ? col.Attribute("DbType").Value : "",
                        IsDbGenerated = col.Attribute("IsDbGenerated") != null ? col.Attribute("IsDbGenerated").Value.ToLower() == "true" : false,
                        IsPrimaryKey = col.Attribute("IsPrimaryKey") != null ? col.Attribute("IsPrimaryKey").Value.ToLower() == "true" : false,
                        Name = col.Attribute("Name") != null ? col.Attribute("Name").Value : ""
                    };
                    t.Columns.Add(c);
                }

                var ass = tab.Element(XName.Get("Type", "http://schemas.microsoft.com/linqtosql/dbml/2007")).Elements(XName.Get("Association", "http://schemas.microsoft.com/linqtosql/dbml/2007"));
                foreach (var item in ass)
                {
                    DBAssociation a = new DBAssociation()
                    {
                        Name = item.Attribute("Name") != null ? item.Attribute("Name").Value : "",
                        OtherKey = item.Attribute("OtherKey") != null ? item.Attribute("OtherKey").Value : "",
                        ThisKey = item.Attribute("ThisKey") != null ? item.Attribute("ThisKey").Value : "",
                        IsForeignKey = item.Attribute("IsForeignKey") != null ? item.Attribute("IsForeignKey").Value.ToLower() == "true" : false
                    };
                    t.Associations.Add(a);
                }
                collection.Add(t);
            }
            return collection;
        }

        #endregion
    }
}

   在转化为我们的实体类,我们剩下的就是编写我们的CodeSmith模板了(更多知识可以参考CodeSmith模板):

<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" Debug="False" Description="Template description here." %>

<%@ Import NameSpace="System" %>
<%@ Import NameSpace="System.Xml" %>
<%@ Import NameSpace="System.Text" %>
<%@ Import NameSpace="System.Collections.Generic" %>
<%@ Assembly Name="DbmlToTable" %>

--Code By Wolf

<%= this.GeneratorTableSql(_DbTableCollection) %>

    在codeSimth中我们建立了一个集合属性传递实体类DBTable和一个转化TSql辅助方法.

      在控制台调用编译模板以及输出:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DbmlToTable
{
    class Program
    {
        static void Main(string[] args)
        {
            IDbTableCollectionHelper helper = new DbTableCollectionHelper();
            List collection = helper.
                Transport(System.Xml.Linq.XElement.

Load(@"E:/APPCODE/OpenXmlTools/MultipleDocument.Data/MultipleDocumentDB.dbml"));

            CodeSmith.Engine.CodeTemplate template = CodeSimthTemplateHelper.
                CompileTemplate(@"DBMLToTable.cst", w => Console.WriteLine(w));
            if (template != null)
            {
                CodeSimthTemplateHelper.AddPropertyParams(template, new { DbTableCollection = collection });
                string str = template.RenderToString();
                Console.WriteLine(str);
                //System.IO.File.AppendAllText(@"D:/1.sql", str);
            }
            Console.Read();
        }

}

 

   在CodeSimth中就是这么简单,生成相应的模板代码(个人理解CodeSmith就是把代码作为字符串输出)。

在上面到我的CodeSmith模板编译辅助类,在上一篇通过代码生成机制实现强类型编程-CodeSmith版也有,在这里也附带上:需要引用CodeSmith.Engine.dll.

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using CodeSmith.Engine;

using Wolf.NameValueDictionary;

namespace DbmlToTable

{

public class CodeSimthTemplateHelper

{

     public static CodeTemplate CompileTemplate(string templateName, Action errorWriter)

     {

           CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateName); compiler.Compile();

          if (compiler.Errors.Count == 0)

           {

           return compiler.CreateInstance();

           }

       else

         {

           for (int i = 0; i < compiler.Errors.Count; i++)

        {

            errorWriter(compiler.Errors[i].ToString());

         }

        return null;

       }

}

 

public static void AddPropertyParams(CodeTemplate template,object param)

{

      NameValueDictionary dict = new NameValueDictionary(param);

       AddPropertyParams(template, dict);

}

 

public static void AddPropertyParams(CodeTemplate template, NameValueDictionary param)

{

          NameValueDictionary dict = new NameValueDictionary(param);

          foreach (var item in dict.Keys)

          {

                template.SetProperty(item, dict[item]);

           }

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值