讀取數據庫信息並生成表設計文檔Word版本

一、參考C#代碼mysql

using Help.DBAccessLayer.Business;
using Help.DBAccessLayer.Model.SqlGenerator;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MSWord = Microsoft.Office.Interop.Word;

namespace MainTest.TestModel
{
    public class GenerateWordDBDesign
    {
        /// <summary>
        /// 數據庫連接字符串
        /// </summary>
        private string _DbConnectionString = "";

        /// <summary>
        /// 數據庫名稱
        /// </summary>
        private string dataBaseName = "master";

        /// <summary>
        /// 是否使用測試數據
        /// </summary>
        private readonly bool _isMock = true;

        /// <summary>
        /// 因爲使用的是COM庫,所以有許多變量須要用Missing.Value代替
        /// </summary>
        private Object Nothing = Missing.Value;

        /// <summary>
        /// 寫入黑體文本
        /// </summary>
        private object unite = MSWord.WdUnits.wdStory;

        /// <summary>
        /// 有長度的類型列表
        /// </summary>
        private readonly List<string> useLengthList = new List<string>(){
            "varchar",
            "nvarchar",
        };

        /// <summary>
        /// 有小數的類型列表
        /// </summary>
        private readonly List<string> digitalList = new List<string>()
        {
             "decimal",
            "numeric",
        };

        /// <summary>
        /// 獲取數據庫中的全部表結構信息等,如今的問題是table的cell 的 高度控制很差,內容是上對齊的 20180316
        /// </summary>
        public void Generate()
        {
            MDataBaseDefine res = getData();

            object path;                              //文件路徑變量
            MSWord.Application wordApp;
            MSWord.Document wordDoc;

            path = Environment.CurrentDirectory + "\\" + DateTime.Now.ToString("yyyyMMdd") + "_" + this.dataBaseName + ".doc";
            wordApp = new MSWord.Application();

            wordApp.Visible = true;//使文檔可見

            //若是已存在,則刪除
            if (File.Exists((string)path))
            {
                File.Delete((string)path);
            }


            //因爲使用的是COM庫,所以有許多變量須要用Missing.Value代替
            wordDoc = wordApp.Documents.Add(ref Nothing, ref Nothing, ref Nothing, ref Nothing);

            //頁面設置
            wordDoc.PageSetup.PaperSize = MSWord.WdPaperSize.wdPaperA4;//設置紙張樣式爲A4紙
            wordDoc.PageSetup.Orientation = MSWord.WdOrientation.wdOrientPortrait;//排列方式爲垂直方向
            wordDoc.PageSetup.TopMargin = 57.0f;
            wordDoc.PageSetup.BottomMargin = 57.0f;
            wordDoc.PageSetup.LeftMargin = 57.0f;
            wordDoc.PageSetup.RightMargin = 57.0f;
            wordDoc.PageSetup.HeaderDistance = 30.0f;//頁眉位置

            wordApp.Selection.ParagraphFormat.LineSpacing = 16f;//設置文檔的行間距
            wordApp.Selection.ParagraphFormat.FirstLineIndent = 30;//首行縮進的長度

            this.AddHeading1("物理模型設計", wordDoc);
            this.DrawTableCountInfo(wordApp, wordDoc, res);

            wordDoc.Content.InsertAfter("\n");//這一句與下一句的順序不能顛倒,緣由還沒搞透
            wordApp.Selection.EndKey(ref unite, ref Nothing);//這一句不加,有時候好像也不出問題,不過仍是加了安全

            this.AddHeading2("2 表描述", wordDoc);
            int tableIndex = 1;
            foreach (var item in res.TableList)
            {
                this.DrawTableDetailInfo(wordApp, wordDoc, tableIndex, item);
                tableIndex++;
            }

            wordDoc.Content.InsertAfter("\n");

            // WdSaveFormat爲Word 2003文檔的保存格式
            // office 2007就是wdFormatDocumentDefault
            object format = MSWord.WdSaveFormat.wdFormatDocumentDefault;
            //將wordDoc文檔對象的內容保存爲DOCX文檔
            wordDoc.SaveAs(ref path, ref format, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing);

            wordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
            //關閉wordApp組件對象
            wordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
            Console.WriteLine(path + " 建立完畢!");
            Console.ReadKey();

        }

        /// <summary>
        /// 繪製表詳細
        /// </summary>
        /// <param name="wordApp">Word App</param>
        /// <param name="wordDoc">Word Doc</param>
        /// <param name="tableIndex">表格序號</param>
        /// <param name="tableDefine">表定義對象</param>
        private void DrawTableDetailInfo(MSWord.Application wordApp, MSWord.Document wordDoc, int tableIndex, MTableDefine tableDefine)
        {
            // 這一句與下一句的順序不能顛倒,緣由還沒搞透
            // wordDoc.Content.InsertAfter("\n");

            // 這一句不加,有時候好像也不出問題,不過仍是加了安全
            wordApp.Selection.EndKey(ref unite, ref Nothing);

            this.AddHeading4("2." + tableIndex + " " + tableDefine.TableName + "表的卡片", wordDoc);

            // 這一句與下一句的順序不能顛倒,緣由還沒搞透
            // wordDoc.Content.InsertAfter("\n"); 
            // 將光標移動到文檔末尾
            wordApp.Selection.EndKey(ref unite, ref Nothing);
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphLeft;

            int tableRow = tableDefine.FieldList.Count + 2;
            int tableColumn = 9;


            // 定義一個Word中的表格對象
            MSWord.Table table = wordDoc.Tables.Add(wordApp.Selection.Range,
            tableRow, tableColumn, ref Nothing, ref Nothing);

            // 默認建立的表格沒有邊框,這裏修改其屬性,使得建立的表格帶有邊框 
            // 這個值能夠設置得很大,例如五、13等等
            table.Borders.Enable = 1;

            // 設置 每一列的 寬度
            table.Columns[1].Width = 30;
            table.Columns[2].Width = 100;
            table.Columns[3].Width = 90;
            table.Columns[4].Width = 50;
            table.Columns[5].Width = 30;
            table.Columns[6].Width = 30;
            table.Columns[7].Width = 30;
            table.Columns[8].Width = 55;
            table.Columns[9].Width = 75;

            // 橫向合併
            table.Cell(1, 1).Merge(table.Cell(1, 9));
            table.Cell(1, 1).Range.Text = tableDefine.TableName;
            table.Cell(1, 1).Range.Shading.BackgroundPatternColor = Microsoft.Office.Interop.Word.WdColor.wdColorGray25;

            //表格的索引是從1開始的。
            table.Cell(2, 1).Range.Text = "是否主鍵";
            table.Cell(2, 2).Range.Text = "字段名";
            table.Cell(2, 3).Range.Text = "字段描述";
            table.Cell(2, 4).Range.Text = "數據類型";
            table.Cell(2, 5).Range.Text = "長度";
            table.Cell(2, 6).Range.Text = "可空";
            table.Cell(2, 7).Range.Text = "約束";
            table.Cell(2, 8).Range.Text = "缺省值";
            table.Cell(2, 9).Range.Text = "備註";


            for (int i = 3; i <= tableRow; i++)
            {
                int row = i;
                var field = tableDefine.FieldList[i - 3];

                // 是否主鍵
                if (field.IsPrimaryKey)
                {
                    table.Cell(row, 1).Range.Text = "";
                }
                else
                {
                    table.Cell(row, 1).Range.Text = "";
                }

                // 字段名
                table.Cell(row, 2).Range.Text = field.FieldName;
                if (string.IsNullOrEmpty(field.FieldNameCH) && field.FieldName == "ID")
                {
                    // 字段描述
                    table.Cell(row, 3).Range.Text = "主鍵ID";
                }
                else
                {
                    // 字段描述
                    table.Cell(row, 3).Range.Text = field.FieldNameCH;
                }

                // 數據類型
                table.Cell(row, 4).Range.Text = field.DataType;

                if (this.digitalList.Contains(field.DataType))
                {
                    table.Cell(row, 5).Range.Text = field.Length.ToString() + "," + field.DigitalLength;
                }

                else if (this.useLengthList.Contains(field.DataType))
                {
                    // 長度
                    table.Cell(row, 5).Range.Text = field.Length.ToString();
                }
                else
                {
                    table.Cell(row, 5).Range.Text = string.Empty;
                }

                // 是否可空
                if (field.IsNullable)
                {
                    table.Cell(row, 6).Range.Text = "";
                }
                else
                {
                    table.Cell(row, 6).Range.Text = "";
                }

                // 約束
                table.Cell(row, 7).Range.Text = field.ValueConstraint;

                // 缺省值
                table.Cell(row, 8).Range.Text = field.DefaultValue;

                // 備註
                table.Cell(row, 9).Range.Text = field.ProjectSignificance;
            }

            //設置table樣式
            //table.Rows.HeightRule = MSWord.WdRowHeightRule.wdRowHeightAtLeast;//高度規則是:行高有最低值下限?
            //table.Rows.Height = wordApp.CentimetersToPoints(float.Parse("0.8"));// 

            table.Range.Font.Size = 9.5F;
            table.Range.Font.Bold = 0;
            table.Range.Font.Name = "新宋體";

            table.Range.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphLeft;//表格文本居中

            table.Range.Cells.VerticalAlignment = MSWord.WdCellVerticalAlignment.wdCellAlignVerticalBottom;//文本垂直貼到底部

            // 設置table邊框樣式
            table.Borders.OutsideLineStyle = MSWord.WdLineStyle.wdLineStyleSingle;//表格外框是雙線
            table.Borders.InsideLineStyle = MSWord.WdLineStyle.wdLineStyleSingle;//表格內框是單線

            // 加粗
            table.Rows[1].Range.Font.Bold = 1;
            table.Rows[1].Range.Font.Size = 9.5F;

            // 加粗
            table.Rows[2].Range.Font.Bold = 1;
            table.Rows[2].Range.Font.Size = 9.5F;
        }

        /// <summary>
        /// 添加標題1
        /// </summary>
        /// <param name="s"></param>
        /// <param name="wordDoc"></param>
        private void AddHeading1(string s, MSWord.Document wordDoc)
        {
            //Word段落
            Microsoft.Office.Interop.Word.Paragraph p;

            p = wordDoc.Content.Paragraphs.Add(ref Nothing);

            //設置段落中的內容文本
            p.Range.Text = s;

            //設置爲一號標題
            object style = Microsoft.Office.Interop.Word.WdBuiltinStyle.wdStyleHeading1;

            p.set_Style(ref style);

            //添加到末尾
            p.Range.InsertParagraphAfter();  //在應用 InsertParagraphAfter 方法以後,所選內容將擴展至包括新段落。
        }

        /// <summary>
        /// 添加標題2
        /// </summary>
        /// <param name="s"></param>
        /// <param name="wordDoc"></param>
        private void AddHeading2(string s, MSWord.Document wordDoc)
        {
            // Word段落
            Microsoft.Office.Interop.Word.Paragraph p;

            p = wordDoc.Content.Paragraphs.Add(ref Nothing);

            // 設置段落中的內容文本
            p.Range.Text = s;

            //設置爲一號標題
            object style = Microsoft.Office.Interop.Word.WdBuiltinStyle.wdStyleHeading2;
            p.set_Style(ref style);

            // 添加到末尾
            // 在應用 InsertParagraphAfter 方法以後,所選內容將擴展至包括新段落。
            p.Range.InsertParagraphAfter();
        }

        /// <summary>
        /// 添加標題4
        /// </summary>
        /// <param name="s"></param>
        /// <param name="wordDoc"></param>
        private void AddHeading4(string s, MSWord.Document wordDoc)
        {
            //Word段落
            Microsoft.Office.Interop.Word.Paragraph p;

            p = wordDoc.Content.Paragraphs.Add(ref Nothing);
            //設置段落中的內容文本
            p.Range.Text = s;
            //設置爲一號標題
            object style = Microsoft.Office.Interop.Word.WdBuiltinStyle.wdStyleHeading4;
            p.set_Style(ref style);
            //添加到末尾
            p.Range.InsertParagraphAfter();  //在應用 InsertParagraphAfter 方法以後,所選內容將擴展至包括新段落。
        }


        /// <summary>
        /// 繪製表清單
        /// </summary>
        /// <param name="wordApp"></param>
        /// <param name="wordDoc"></param>
        /// <param name="res"></param>
        private void DrawTableCountInfo(MSWord.Application wordApp, MSWord.Document wordDoc, MDataBaseDefine res)
        {
            // 這一句與下一句的順序不能顛倒,緣由還沒搞透
            //wordDoc.Content.InsertAfter("\n");

            // 這一句不加,有時候好像也不出問題,不過仍是加了安全
            wordApp.Selection.EndKey(ref unite, ref Nothing);

            this.AddHeading2("1 表清單", wordDoc);

            //將光標移動到文檔末尾
            wordApp.Selection.EndKey(ref unite, ref Nothing);
            wordApp.Selection.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphLeft;

            int tableRow = res.TableList.Count + 1;
            int tableColumn = 3;


            // 定義一個Word中的表格對象
            MSWord.Table table = wordDoc.Tables.Add(wordApp.Selection.Range,
            tableRow, tableColumn, ref Nothing, ref Nothing);

            // 默認建立的表格沒有邊框,這裏修改其屬性,使得建立的表格帶有邊框 
            table.Borders.Enable = 1;//這個值能夠設置得很大,例如五、13等等

            // 表格的索引是從1開始的。
            table.Cell(1, 1).Range.Text = "序號";
            table.Cell(1, 2).Range.Text = "代碼";
            table.Cell(1, 3).Range.Text = "描述";

            for (int i = 1; i < tableRow; i++)
            {
                int row = i + 1;
                var tableInfo = res.TableList[i - 1];
                table.Cell(row, 1).Range.Text = i + ".";
                table.Cell(row, 2).Range.Text = tableInfo.TableName;
                table.Cell(row, 3).Range.Text = tableInfo.TableNameCH;
            }

            // 設置table樣式
            // 高度規則是:行高有最低值下限?
            table.Rows.HeightRule = MSWord.WdRowHeightRule.wdRowHeightAtLeast;
            //table.Rows.Height = wordApp.CentimetersToPoints(float.Parse("0.8"));// 

            table.Range.Font.Size = 11F;
            table.Range.Font.Bold = 0;
            table.Range.Font.Name = "新宋體";

            // 表格文本居左
            table.Range.ParagraphFormat.Alignment = MSWord.WdParagraphAlignment.wdAlignParagraphCenter;

            // 文本垂直貼到底部
            table.Range.Cells.VerticalAlignment = MSWord.WdCellVerticalAlignment.wdCellAlignVerticalBottom;

            // 設置table邊框樣式
            table.Borders.OutsideLineStyle = MSWord.WdLineStyle.wdLineStyleSingle;//表格外框是雙線
            table.Borders.InsideLineStyle = MSWord.WdLineStyle.wdLineStyleSingle;//表格內框是單線

            // 加粗
            table.Rows[1].Range.Font.Bold = 1;
            table.Rows[1].Range.Font.Size = 11F;

            //將第 1列寬度設置爲90
            table.Columns[1].Width = 90;

            //將其餘列的寬度都設置爲75
            for (int i = 2; i <= tableColumn; i++)
            {
                table.Columns[i].Width = 200;
            }
        }

        /// <summary>
        /// 讀取數據庫及表結構信息
        /// </summary>
        /// <returns></returns>
        private MDataBaseDefine getData()
        {
            if (_isMock)
            {
                return new MDataBaseDefine()
                {
                    TableList = new List<MTableDefine>()
                    {
                         new MTableDefine(){
                              FieldList = new List<MFieldDefine>(){
                               new MFieldDefine(){
                                DataType = "varchar",
                                 DefaultValue = string.Empty,
                                  DigitalLength = 3,
                                   FieldFormat = string.Empty,
                                    FieldName = "ID",
                                     FieldNameCH = string.Empty,
                                      ForeignRelation = string.Empty,
                                       IsNullable = false,
                                        Length = 128,
                                         IsAutoIncrement = false,
                                          IsPrimaryKey = true,
                                          
                               },
                               new MFieldDefine(){
                                DataType = "varchar",
                                 DefaultValue = string.Empty,
                                  DigitalLength = 3,
                                   FieldFormat = string.Empty,
                                    FieldName = "UserName",
                                     FieldNameCH = "用戶名稱",
                                      ForeignRelation = string.Empty,
                                       IsNullable = false,
                                        Length = 128,
                                         IsAutoIncrement = false,
                                          IsPrimaryKey = false,
                                          
                               }
                              },
                               PrimaryKey = "ID",
                                TableDescrption = string.Empty,
                                 TableName = "User",
                                  TableNameCH = string.Empty
                         }
                    }
                };
            }
            else
            {
                var res = new BGetSchema().GenerateDataBaseDefine(this._DbConnectionString);

                string json = JsonConvert.SerializeObject(res);

                // 存個表

                string fileName = @"C:\Julius_J_Zhu\09DataLayer\MainTest\documents\" + this.dataBaseName + "_JSON_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";

                this.saveFileName(fileName, json);

                // 去除 含有 下劃線的臨時表
                res.TableList = res.TableList.FindAll(sa => !sa.TableName.Contains("_"));


                return res;
            }
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="name">文件名</param>
        /// <param name="str">文件內容</param>
        private void saveFileName(string name, string str)
        {
            using (FileStream fs2 = new FileStream(name, FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fs2);

                //開始寫入
                sw.Write(str);
                //清空緩衝區
                sw.Flush();
                //關閉流
                sw.Close();
            }

        }
    }
}
View Code

二、所使用的Model類git

2.1 數據庫類sql

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

namespace Help.DBAccessLayer.Model.SqlGenerator
{
    /// <summary>
    /// 數據庫定義
    /// </summary>
    public class MDataBaseDefine
    {
        /// <summary>
        /// 數據庫定義
        /// </summary>
        public string DataBaseName
        {
            get;
            set;
        }

        /// <summary>
        /// 數據庫類型
        /// </summary>
        public MDataBaseType DataBaseType
        {
            get;
            set;
        }

        /// <summary>
        /// 服務器地址
        /// </summary>
        public string ServerAddress
        {
            get;
            set;
        }

        /// <summary>
        /// 讀寫帳號
        /// </summary>
        public string ReadAccount
        {
            get;
            set;
        }

        /// <summary>
        /// 寫帳號
        /// </summary>
        public string WriteAccount
        {
            get;
            set;
        }

        /// <summary>
        /// 表列表
        /// </summary>
        public List<MTableDefine> TableList
        {
            get;
            set;
        }
    }
}
MDataBaseDefine類

 2.2 表結構類數據庫

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

namespace Help.DBAccessLayer.Model.SqlGenerator
{
    /// <summary>
    /// 表定義
    /// </summary>
    public class MTableDefine
    {
        /// <summary>
        /// 表名(英文)
        /// </summary>
        public string TableName
        {
            get;
            set;
        }

        /// <summary>
        /// 表名(中文)
        /// </summary>
        public string TableNameCH
        {
            get;
            set;
        }

        /// <summary>
        /// 表描述
        /// </summary>
        public string TableDescrption
        {
            get;
            set;
        }

        /// <summary>
        /// 主鍵
        /// </summary>
        public string PrimaryKey
        {
            get;
            set;
        }

        /// <summary>
        /// 字段定義
        /// </summary>
        public List<MFieldDefine> FieldList
        {
            get;
            set;
        }
    }
}
MTableDefine類

 2.3 字段類json

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

namespace Help.DBAccessLayer.Model.SqlGenerator
{
    /// <summary>
    /// 表字段定義
    /// </summary>
    public class MFieldDefine
    {
        /// <summary>
        /// 字段格式
        /// </summary>
        public string FieldFormat;
       
        /// <summary>
        /// 序號
        /// </summary>
        public int Index { get; set; }

        /// <summary>
        /// 字段中文名
        /// </summary>
        public string FieldNameCH
        {
            get;
            set;
        }

        /// <summary>
        /// 字段名
        /// </summary>
        public string FieldName
        {
            get;
            set;
        }

        /// <summary>
        /// 數據類型
        /// </summary>
        public string DataType
        {
            get;
            set;
        }

        /// <summary>
        /// 數據類型長度
        /// </summary>
        public int Length
        {
            get;
            set;
        }

        /// <summary>
        /// 是否可空
        /// </summary>
        public bool IsNullable
        {
            get;
            set;
        }

        /// <summary>
        /// 主鍵
        /// </summary>
        public int PrimaryKeyIndex
        {
            get;
            set;
        }

        /// <summary>
        /// 外部關係
        /// </summary>
        public string ForeignRelation
        {
            get;
            set;
        }

        /// <summary>
        /// 是不是惟一索引
        /// </summary>
        public bool IsUniqueIndex
        {
            get;
            set;
        }

        /// <summary>
        /// 索引序號
        /// </summary>
        public int IndexNo
        {
            get;
            set;
        }

        /// <summary>
        /// 是不是自增加類型
        /// </summary>
        public bool IsAutoIncrement
        {
            get;
            set;
        }

        /// <summary>
        /// 默認值
        /// </summary>
        public string DefaultValue
        {
            get;
            set;
        }

        /// <summary>
        /// 值約束
        /// </summary>
        public string ValueConstraint
        {
            get;
            set;
        }

        /// <summary>
        /// 項目意義
        /// </summary>
        public string ProjectSignificance
        {
            get;
            set;
        }

        public int DigitalLength { get; set; }

        /// <summary>
        /// 是否爲主鍵,聯合主鍵可能會有問題
        /// </summary>
        public bool IsPrimaryKey
        {
            get;
            set;
        }
    }
}
MFieldDefine類

2.4 數據庫類型枚舉安全

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

namespace Help.DBAccessLayer.Model
{
    public enum MDataBaseType
    {
        /// <summary>
        /// 未知數據庫
        /// </summary>
        UNKNOW = 0,

        /// <summary>
        /// The mysql
        /// </summary>
        MYSQL = 1,

        /// <summary>
        /// The sqlserver
        /// </summary>
        SQLSERVER = 2,

        /// <summary>
        /// DB2
        /// </summary>
        DB2 = 3
    }
}
MDataBaseType枚舉

三、獲取數據庫結構相關服務器

3.1 獲取數據庫結構業務層ide

using Help.DBAccessLayer.Factory;
using Help.DBAccessLayer.Model;
using Help.DBAccessLayer.Model.SqlGenerator;
using IBM.Data.DB2;
using System;
using System.Collections.Generic;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Help.DBAccessLayer.Business
{
    public class BGetSchema
    {
        public List<MTableDesc> GetTableList(string creator)
        {
            string connstr = ConnectionFactory.TRSDbConnString;

            List<MTableDesc> ret = null;

            using (DB2Connection conn = new DB2Connection(connstr))
            {
                conn.Open();
                var dao = DALFactory.GetSchemaDAO(MDataBaseType.DB2, MDBAccessType.WRITE);

                ret = dao.GetTableList(conn, creator);
            }

            return ret;
        }

        public List<MColumn> GetColumnList(string tableName)
        {
            string connstr = ConnectionFactory.TRSDbConnString;
            List<MColumn> ret = new List<MColumn>();
            using (DB2Connection conn = new DB2Connection(connstr))
            {
                conn.Open();
                var dao = DALFactory.GetSchemaDAO(MDataBaseType.DB2, MDBAccessType.WRITE);

                ret = dao.GetColumnList(conn, tableName);
            }

            return ret;
        }

        public MDataBaseDefine GenerateDataBaseDefine(string connstr)
        {
            MDataBaseDefine ret = null;
            using (SqlConnection conn = new SqlConnection(connstr))
            {
                conn.Open();
                var dao = DALFactory.GetSchemaDAO(MDataBaseType.SQLSERVER, MDBAccessType.READONLY);
                ret = dao.GenerateDataBaseDefine(conn);
            }

            return ret;
        }
    }
}
BGetSchema類
3.2 獲取數據庫結構工廠
using Help.DBAccessLayer.DB2DAL;
using Help.DBAccessLayer.IDAL;
using Help.DBAccessLayer.Model;
using Help.DBAccessLayer.MySQLDAL;

using SQLServer = Help.DBAccessLayer.SQLServer;
using Help.DBAccessLayer.OleDbDAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Help.DBAccessLayer.Factory
{
    public class DALFactory
    {
        public static IGetSchema GetSchemaDAO(MDataBaseType dbType, MDBAccessType accessType)
        {
            switch (dbType)
            {
                case MDataBaseType.DB2:
                    return new DGetSchema();
                case MDataBaseType.SQLSERVER:
                    return new Help.DBAccessLayer.SQLServer.DGetSchema();
            }

            throw new Exception(string.Format("未實現的IGetSchema接口:數據庫類型:{0},數據庫訪問類型:{1}", dbType.ToString(), accessType.ToString()));
        }   
    }
}

 3.3 DGetSchema 獲取數據庫結構 SQL 實現sqlserver

using Help.DBAccessLayer.Model;
using Help.DBAccessLayer.Model.SqlGenerator;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Help.DBAccessLayer.IDAL
{
    public interface IGetSchema
    {
        MDataBaseDefine GenerateDataBaseDefine(System.Data.IDbConnection conn);
    }
}
using Help.DBAccessLayer.IDAL;
using Help.DBAccessLayer.Model.SqlGenerator;
using Help.DBAccessLayer.Util;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Help.DBAccessLayer.SQLServer
{
    public class DGetSchema : IGetSchema
    {
        public MDataBaseDefine GenerateDataBaseDefine(System.Data.IDbConnection conn)
        {
            MDataBaseDefine database = new MDataBaseDefine();
            database.TableList = new List<MTableDefine>();

            // 獲取全部表名
            List<string> tableNameList = this.GetTableNameList(conn);

            foreach (var tableName in tableNameList)
            {
                var table = this.GetTableDefine(conn, tableName);
                database.TableList.Add(table);
            }


            // 填充索引信息
            List<MTableIndex> indexList = this.GetIndexInfo(conn);

            var group = from p in indexList
                        group p by new { p.TableName } into g
                        select new { g.Key };
            foreach (var g in group)
            {
                var tableFind = database.TableList.Find(sa => sa.TableName == g.Key.TableName);
                if (tableFind != null)
                {
                    var columns = tableFind.FieldList;
                    var indexs = indexList.FindAll(sa => sa.TableName == g.Key.TableName);

                    indexs.ForEach(sa =>
                    {
                        var column = columns.Find(p => p.FieldName == sa.ColumnName);
                        if (sa.IsUnique)
                        {
                            column.IsUniqueIndex = true;
                        }
                        else
                        {
                            column.IndexNo = columns.Max(q => q.IndexNo) + 1;
                        }
                    });
                }
            }

            return database;
        }

        private List<string> GetTableNameList(System.Data.IDbConnection conn)
        {
            string queryTableListSql = "SELECT name FROM SYSOBJECTS WHERE TYPE='U' and category=0 order by name;";
            SqlCommand comm = new SqlCommand(queryTableListSql, (SqlConnection)conn);
            SqlDataReader reader = comm.ExecuteReader();

            List<string> tableNameList = new List<string>();

            while (reader.Read())
            {
                string name = reader["name"] == DBNull.Value ? string.Empty : reader["name"].ToString();
                tableNameList.Add(name);
            }

            return tableNameList;
        }

        private MTableDefine GetTableDefine(System.Data.IDbConnection conn, string tableName)
        {
            MTableDefine table = new MTableDefine();
            table.TableName = tableName;
            string sql = string.Format(@"
SELECT 
    TableName       = case when a.colorder=1 then d.name else '' end,
    TableNameCH     = case when a.colorder=1 then isnull(f.value,'') else '' end,
    FieldIndex   = a.colorder,
    FieldName     = a.name,
    IsIdentity       = case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then 'true'else 'false' end,
    IsPrimaryKey       = case when exists(SELECT 1 FROM sysobjects where xtype='PK' and parent_obj=a.id and name in (
                     SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then 'true' else 'false' end,
    DataType       = b.name,
    DataTypeLength       = COLUMNPROPERTY(a.id,a.name,'PRECISION'),
    DigitalLength   = isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
    IsNullable     = case when a.isnullable=1 then 'true'else 'false' end,
    DefaultValue     = isnull(e.text,''),
    FieldNameCH   = isnull(g.[value],'')
FROM 
    syscolumns a
left join 
    systypes b 
on 
    a.xusertype=b.xusertype
inner join 
    sysobjects d 
on 
    a.id=d.id  and d.xtype='U' and  d.name<>'dtproperties'
left join 
    syscomments e 
on 
    a.cdefault=e.id
left join 
sys.extended_properties   g 
on 
    a.id=G.major_id and a.colid=g.minor_id  
left join
sys.extended_properties f
on 
    d.id=f.major_id and f.minor_id=0
where 
    d.name='{0}'    --若是隻查詢指定表,加上此紅色where條件,tablename是要查詢的表名;去除紅色where條件查詢說有的表信息
order by 
    a.id,a.colorder;", tableName);

            SqlCommand comm = new SqlCommand(sql, (SqlConnection)conn);
            SqlDataReader reader = comm.ExecuteReader();
            List<MFieldDefine> fieldList = new List<MFieldDefine>();
            while (reader.Read())
            {
                MFieldDefine field = new MFieldDefine();
                table.TableNameCH = reader["TableNameCH"] == DBNull.Value ? string.Empty : reader["TableNameCH"].ToString();
                field.Index = DBUtil.GetDBValueInt(reader, "FieldIndex", 0);
                field.FieldName = DBUtil.GetDBValueStr(reader, "FieldName", string.Empty);
                field.IsAutoIncrement = DBUtil.GetDBValueBool(reader, "IsIdentity", false);

                bool IsPrimaryKey = DBUtil.GetDBValueBool(reader, "IsPrimaryKey", false);
                int maxPrimaryKeyIndex = fieldList != null && fieldList.Count > 0 ? fieldList.Max(sa => sa.PrimaryKeyIndex) : 0;

                if (IsPrimaryKey)
                {
                    field.PrimaryKeyIndex = maxPrimaryKeyIndex + 1;
                }

                field.IsPrimaryKey = IsPrimaryKey;

                field.DataType = DBUtil.GetDBValueStr(reader, "DataType", string.Empty);
                field.Length = DBUtil.GetDBValueInt(reader, "DataTypeLength", 0);
                field.DigitalLength = DBUtil.GetDBValueInt(reader, "DigitalLength", 0);
                field.IsNullable = DBUtil.GetDBValueBool(reader, "IsNullable", false);
                field.DefaultValue = DBUtil.GetDBValueStr(reader, "DefaultValue", string.Empty);

                // 處理默認值
                if (!string.IsNullOrEmpty(field.DefaultValue))
                {
                    string[] twoBracketsSpecial = { "int", "tinyint" };

                    if (twoBracketsSpecial.Contains(field.DataType.ToLower()))
                    {
                        field.DefaultValue = field.DefaultValue.Replace("(", string.Empty).Replace(")", string.Empty);
                    }
                    else
                    {
                        // 只有一個括號
                        field.DefaultValue = field.DefaultValue.Substring(1, field.DefaultValue.Length - 2);
                    }
                }

                field.FieldNameCH = DBUtil.GetDBValueStr(reader, "FieldNameCH", string.Empty);
                fieldList.Add(field);
            }

            table.FieldList = fieldList;




            return table;

        }

        private List<MTableIndex> GetIndexInfo(System.Data.IDbConnection conn)
        {
            string sql = @"SELECT 
    TableId=O.[object_id],
    TableName=O.Name,
    IndexId=ISNULL(KC.[object_id],IDX.index_id),
    IndexName=IDX.Name,
    IndexType=ISNULL(KC.type_desc,''),
    Index_Column_id=IDXC.index_column_id,
    ColumnID=C.Column_id,
    ColumnName=C.Name,
    Sort=CASE INDEXKEY_PROPERTY(IDXC.[object_id],IDXC.index_id,IDXC.index_column_id,'IsDescending')
        WHEN 1 THEN 'DESC' WHEN 0 THEN 'ASC' ELSE '' END,
    PrimaryKey=IDX.is_primary_key,
    IsUnique=IDX.is_unique,
    Ignore_dup_key=IDX.ignore_dup_key,
    Disabled=IDX.is_disabled,
    Fill_factor=IDX.fill_factor,
    Padded=IDX.is_padded
FROM sys.indexes IDX
    INNER JOIN sys.index_columns IDXC
        ON IDX.[object_id]=IDXC.[object_id]
            AND IDX.index_id=IDXC.index_id
    LEFT JOIN sys.key_constraints KC
        ON IDX.[object_id]=KC.[parent_object_id]
            AND IDX.index_id=KC.unique_index_id
    INNER JOIN sys.objects O
        ON O.[object_id]=IDX.[object_id]
    INNER JOIN sys.columns C
        ON O.[object_id]=C.[object_id]
            AND O.type='U'
            AND O.is_ms_shipped=0
            AND IDXC.Column_id=C.Column_id
WHERE IDX.is_primary_key<>1
     AND O.Name NOT LIKE 'sys%';";

            SqlCommand comm = new SqlCommand(sql, (SqlConnection)conn);
            SqlDataReader reader = comm.ExecuteReader();
            List<MTableIndex> list = new List<MTableIndex>();
            while (reader.Read())
            {
                MTableIndex model = new MTableIndex();
                model.TableName = DBUtil.GetDBValueStr(reader, "TableName");
                model.IndexType = DBUtil.GetDBValueStr(reader, "IndexType");
                model.IndexName = DBUtil.GetDBValueStr(reader, "IndexName");
                model.ColumnName = DBUtil.GetDBValueStr(reader, "ColumnName");
                model.IsUnique = DBUtil.GetDBValueBool(reader, "IsUnique");
                model.Sort = DBUtil.GetDBValueStr(reader, "Sort");

                list.Add(model);
            }

            return list;
        }
    }
}
View Code

4 生成文檔結果測試

相關文章
相關標籤/搜索