コード例 #1
0
ファイル: OracleTableInfo.cs プロジェクト: ilwu/RbtUtil.Net
        public Dictionary <string, OracleTableInfo> GetAllTable(OracleDBUtil dbUtil, string schema, string testModelTable = "")
        {
            // =======================================================
            // 查詢 所有的欄位資訊
            // =======================================================
            // 兜組SQL
            var columnsQSql = new StringBuilder();

            columnsQSql.Append("SELECT col.OWNER, ");
            columnsQSql.Append("	   col.TABLE_NAME, ");
            columnsQSql.Append("	   tabComt.COMMENTS AS TABLE_COMMENTS, ");
            columnsQSql.Append("	   col.COLUMN_ID, ");
            columnsQSql.Append("	   col.COLUMN_NAME, ");
            columnsQSql.Append("	   col.DATA_TYPE, ");
            columnsQSql.Append("	   col.DATA_LENGTH, ");
            columnsQSql.Append("	   col.DATA_PRECISION, ");
            columnsQSql.Append("	   col.DATA_SCALE, ");
            columnsQSql.Append("	   col.DATA_DEFAULT, ");
            columnsQSql.Append("	   col.CHAR_LENGTH, ");
            columnsQSql.Append("	   col.NULLABLE, ");
            columnsQSql.Append("	   colComt.COMMENTS ");
            columnsQSql.Append("FROM   ALL_TAB_COLUMNS col ");
            //columnsQSql.Append("	   JOIN ALL_TABLES tab ");
            //columnsQSql.Append("		 ON col.OWNER = tab.OWNER ");
            //columnsQSql.Append("			AND col.TABLE_NAME = tab.TABLE_NAME ");
            columnsQSql.Append("	   LEFT JOIN ALL_COL_COMMENTS colComt ");
            columnsQSql.Append("			  ON col.OWNER = colComt.Owner ");
            columnsQSql.Append("				 AND col.TABLE_NAME = colComt.TABLE_NAME ");
            columnsQSql.Append("				 AND col.COLUMN_NAME = colComt.COLUMN_NAME ");
            columnsQSql.Append("	   LEFT JOIN sys.USER_TAB_COMMENTS tabComt ");
            columnsQSql.Append("			  ON tabComt.TABLE_TYPE in ('TABLE','VIEW') ");             //改為連 View 一起撈
            columnsQSql.Append("				 AND tabComt.TABLE_NAME = col.TABLE_NAME ");
            columnsQSql.Append("WHERE  col.OWNER = '" + schema + "' ");
            // 測試縮限範圍
            if (StringUtil.NotEmpty(testModelTable))
            {
                columnsQSql.Append("AND  col.TABLE_NAME = '" + testModelTable + "' ");
            }
            columnsQSql.Append("ORDER  BY col.TABLE_NAME, ");
            columnsQSql.Append("		  col.COLUMN_ID ");

            // 查詢所有的欄位List
            var allColumnList = dbUtil.Query(columnsQSql.ToString());
            // 依據 table 分類
            var tableColumnProcResult = Process(allColumnList);

            // =======================================================
            // 查詢 所有的欄位資訊
            // =======================================================
            var pKeyQSql = new StringBuilder();

            pKeyQSql.Append("SELECT C.OWNER, ");
            pKeyQSql.Append("	   C.TABLE_NAME, ");
            pKeyQSql.Append("	   D.POSITION, ");
            pKeyQSql.Append("	   D.COLUMN_NAME ");
            pKeyQSql.Append("FROM   ALL_CONSTRAINTS C ");
            pKeyQSql.Append("	   JOIN ALL_CONS_COLUMNS D ");
            pKeyQSql.Append("		 ON C.OWNER = D.OWNER ");
            pKeyQSql.Append("			AND C.CONSTRAINT_NAME = D.CONSTRAINT_NAME ");
            pKeyQSql.Append("WHERE  C.CONSTRAINT_TYPE = 'P' ");
            pKeyQSql.Append("	   AND C.OWNER = '"+ schema + "' ");
            // 測試縮限範圍
            if (StringUtil.NotEmpty(testModelTable))
            {
                columnsQSql.Append("AND  C.TABLE_NAME = '" + testModelTable + "' ");
            }
            pKeyQSql.Append("ORDER  BY C.TABLE_NAME, ");
            pKeyQSql.Append("		  D.POSITION ");

            var allPKeyColumnList = dbUtil.Query(pKeyQSql.ToString());
            // 依據 table 分類
            var pkColumnProcResult = Process(allPKeyColumnList);

            // =======================================================
            // 組 tableInfo
            // =======================================================
            var tableInfoMap = new Dictionary <string, OracleTableInfo>();

            foreach (var tableName in tableColumnProcResult.ColumnInfoListByTableName.Keys)
            {
                var tableInfo = new OracleTableInfo();
                // 一般欄位
                tableInfo.ColumnDataMapList      = tableColumnProcResult.ColumnInfoListByTableName[tableName];
                tableInfo.ColumnDataMapByColName = tableColumnProcResult.ColumnInfoByColNameTableName[tableName];
                tableInfo.ColumnNameSet          = tableColumnProcResult.ColumnNameSetByTableName[tableName];
                // PK欄位

                if (pkColumnProcResult.ColumnInfoListByTableName.ContainsKey(tableName))
                {
                    tableInfo.PKeyDataMapList = pkColumnProcResult.ColumnInfoListByTableName[tableName];
                    tableInfo.PKeySet         = pkColumnProcResult.ColumnNameSetByTableName[tableName];
                }
                else
                {
                    tableInfo.PKeyDataMapList = new List <IDictionary <string, object> >();
                    tableInfo.PKeySet         = new List <string>();
                }

                // PUT
                tableInfoMap.Add(tableName, tableInfo);
            }
            return(tableInfoMap);
        }
コード例 #2
0
        public void proc(
            string OUTPUT_PTAH,
            string schema,
            string classNamespace,
            string classPrefix,
            string nameMapClassName,
            OracleDBUtil dbUtil,
            string testModelTable = ""
            )
        {
            var tb = new OracleTableInfo();

            var fileUtil = new FileUtil();

            Console.WriteLine("讀取 table 資訊");
            var tableInfoList = tb.GetAllTable(dbUtil, schema, testModelTable);

            Console.WriteLine("讀取完成!: " + tableInfoList.Count);

            if (testModelTable.NotEmpty() && tableInfoList.Count == 0)
            {
                throw new Exception("找不到指定的 Table");
            }

            foreach (KeyValuePair <string, OracleTableInfo> table in tableInfoList)
            {
                //=======================================
                //取得 table 資料
                //=======================================
                //table 代號
                var tableName = table.Key;
                //OracleTableInfo
                var tableInfo = table.Value;
                //不存在column資料時跳過
                if (tableInfo.ColumnDataMapList.Count < 1)
                {
                    continue;
                }

                //table 註解
                var tableComments = prepareStr(replaceBreakLine(tableInfo.ColumnDataMapList[0]["TABLE_COMMENTS"] + "")).Replace(System.Environment.NewLine, "");

                //class Name =
                var className = classPrefix + StringUtil.Convert2CamelCase(tableName) + "";

                //=======================================
                //兜組 base class 代碼
                //=======================================
                //TBMODEL
                var tbModelContent = new StringBuilder();
                tbModelContent.AppendLine("using System;");
                tbModelContent.AppendLine("using System.ComponentModel;");
                tbModelContent.AppendLine("using System.ComponentModel.DataAnnotations;");
                tbModelContent.AppendLine("using System.ComponentModel.DataAnnotations.Schema;");
                tbModelContent.AppendLine("using rbt.util.db.model;");
                tbModelContent.AppendLine("using rbt.DataAnnotations.Validation;");

                tbModelContent.AppendLine("");
                tbModelContent.AppendLine("namespace " + classNamespace);
                tbModelContent.AppendLine("{");
                tbModelContent.AppendLine("    /// <summary>");
                tbModelContent.AppendLine("    /// [" + tableName + " " + tableComments + "] table model");
                tbModelContent.AppendLine("    /// <summary>");
                tbModelContent.AppendLine("    [Table(\"" + tableName + "\")]");
                tbModelContent.AppendLine("    [DisplayName(\"" + tableComments + "\")]");
                tbModelContent.AppendLine("    public class " + className + " : BaseDBEntity");
                tbModelContent.AppendLine("    {");

                //validator
                var validatorContent = new StringBuilder();
                validatorContent.AppendLine("using System;");
                validatorContent.AppendLine("using System.ComponentModel;");
                validatorContent.AppendLine("using System.ComponentModel.DataAnnotations;");
                validatorContent.AppendLine("");
                validatorContent.AppendLine("namespace " + classNamespace + ".validator");
                validatorContent.AppendLine("{");
                validatorContent.AppendLine("    /// <summary>");
                validatorContent.AppendLine("    /// [" + tableName + " " + tableComments + "] table model validator");
                validatorContent.AppendLine("    /// <summary>");
                validatorContent.AppendLine("    [DisplayName(\"" + tableComments + " 欄位驗證\")]");
                validatorContent.AppendLine("    public class " + className + "Validator");
                validatorContent.AppendLine("    {");

                var columnInfoContent = new StringBuilder();
                foreach (Dictionary <string, object> item in tableInfo.ColumnDataMapList)
                {
                    //"COLUMN_NAME"
                    string columnName = prepareStr(StringUtil.SafeTrim(item["COLUMN_NAME"]));
                    //"COMMENTS"
                    string orgComments = replaceBreakLine(StringUtil.SafeTrim(item["COMMENTS"]));
                    string comments    = prepareStr(orgComments);
                    columnInfoContent.AppendLine("        //" + columnName + "\t" + comments);
                }

                tbModelContent.AppendLine();
                tbModelContent.AppendLine(columnInfoContent.ToString());
                tbModelContent.AppendLine();

                foreach (Dictionary <string, object> item in tableInfo.ColumnDataMapList)
                {
                    //=====================================================
                    // 取得欄位參數
                    //=====================================================
                    //"COLUMN_NAME"
                    string columnName = prepareStr(StringUtil.SafeTrim(item["COLUMN_NAME"]));
                    //"DATA_TYPE"
                    string dataType = StringUtil.SafeTrim(item["DATA_TYPE"]);
                    //"COMMENTS"
                    string orgComments = replaceBreakLine(StringUtil.SafeTrim(item["COMMENTS"]));
                    string comments    = prepareStr(orgComments);
                    //DATA_LENGTH
                    int dataLenght = int.Parse(StringUtil.SafeTrim(item["DATA_LENGTH"]));
                    if ("NUMBER".Equals(dataType) && StringUtil.NotEmpty(item["DATA_PRECISION"]))
                    {
                        dataLenght = int.Parse(StringUtil.SafeTrim(item["DATA_PRECISION"]));
                    }

                    //"DATA_SCALE"
                    int dataScale = int.Parse(StringUtil.SafeTrim(item["DATA_SCALE"], "0"));
                    //額外訊息
                    var ExtInfoList = this.parseExtInfo(orgComments);

                    //=====================================================
                    // TBModel
                    //=====================================================
                    tbModelContent.AppendLine("        /// <summary>");
                    tbModelContent.AppendLine("        /// " + columnName + " " + orgComments);
                    tbModelContent.AppendLine("        /// <summary>");
                    //DisplayName
                    tbModelContent.AppendLine("        [DisplayName(\"" + (StringUtil.IsEmpty(comments) ? "未設定" : comments) + "\")]");
                    //NULLABLE
                    //if (!"Y".Equals(StringUtil.SafeTrim(item["NULLABLE"])))
                    //{
                    //    content.AppendLine("        [Required]");
                    //}
                    //StringLength
                    tbModelContent.Append(GetLengthAttr(dataType, StringUtil.SafeTrim(item["CHAR_LENGTH"]), comments));
                    //NumberValidtion
                    tbModelContent.Append(GetNumberValidate(dataType, StringUtil.SafeTrim(item["DATA_PRECISION"]), StringUtil.SafeTrim(item["DATA_SCALE"]), comments));
                    //other Attribute
                    tbModelContent.Append(prepareAttribute(orgComments));
                    //[Key]
                    if (tableInfo.PKeySet.Contains(columnName))
                    {
                        tbModelContent.AppendLine("        [Key]");
                    }

                    tbModelContent.AppendLine("        public " + getType(dataType, dataLenght, dataScale, tableName + "." + columnName) + " " + columnName);
                    tbModelContent.AppendLine("        {");
                    tbModelContent.AppendLine("            get { return _" + columnName + "; }");
                    tbModelContent.AppendLine("            set { if (!this.GetModeifyField().Contains(\"" + columnName + "\")) this.GetModeifyField().Add(\"" + columnName + "\"); _" + columnName + " = value; }");
                    tbModelContent.AppendLine("        }");
                    tbModelContent.AppendLine("        private " + getType(dataType, dataLenght, dataScale, tableName + "." + columnName) + " _" + columnName + " { get; set; }");
                    tbModelContent.AppendLine("");

                    //=====================================================
                    // TBModel validator
                    //=====================================================
                    validatorContent.AppendLine("        /// <summary>");
                    validatorContent.AppendLine("        /// " + columnName + " " + orgComments);
                    validatorContent.AppendLine("        /// <summary>");
                    //[Required]
                    validatorContent.AppendLine("        [Required]");
                    validatorContent.AppendLine("        public " + getType(dataType, dataLenght, dataScale, tableName + "." + columnName) + " " + columnName + " { get; set; }");
                    validatorContent.AppendLine("");

                    //處理日期轉換欄位
                    if ((("varchar2".Equals(dataType) && dataLenght == 7) || ("nvarchar2".Equals(dataType) && dataLenght == 14)) &&
                        (columnName.ToLower().IndexOf("date") >= 0 || columnName.ToLower().IndexOf("day") >= 0))
                    {
                        validatorContent.AppendLine("        /// <summary>");
                        validatorContent.AppendLine("        /// " + columnName + " " + comments + ": 西元日期轉換擴充欄位");
                        validatorContent.AppendLine("        /// </summary>");
                        validatorContent.AppendLine("        [Required]");
                        validatorContent.AppendLine("        public string " + columnName + "_AD { get; set; }");
                        validatorContent.AppendLine("");
                    }
                }

                tbModelContent.AppendLine("        /// <summary>");
                tbModelContent.AppendLine("        /// 回傳 Table 名稱");
                tbModelContent.AppendLine("        /// <summary>");
                tbModelContent.AppendLine("        public override string GetTableName()");
                tbModelContent.AppendLine("        {");
                tbModelContent.AppendLine("            return \"" + tableName + "\";");
                tbModelContent.AppendLine("        }");
                tbModelContent.AppendLine("        ");

                tbModelContent.AppendLine("    }");
                //content.AppendLine("}");
                tbModelContent.AppendLine("");

                //=======================================
                //擴充 model
                //=======================================
                tbModelContent.AppendLine("    /// <summary>");
                tbModelContent.AppendLine("    /// [" + tableName + " " + tableComments + "] 擴充 model");
                tbModelContent.AppendLine("    /// </summary>");
                tbModelContent.AppendLine("    public class " + className + "Ext : " + className);
                tbModelContent.AppendLine("    {");

                foreach (Dictionary <string, object> item in tableInfo.ColumnDataMapList)
                {
                    //"COLUMN_NAME"
                    string columnName = prepareStr(StringUtil.SafeTrim(item["COLUMN_NAME"]));
                    //"DATA_TYPE"
                    string dataType = StringUtil.SafeTrim(item["DATA_TYPE"]).ToLower();
                    //"COMMENTS"
                    string orgComments = replaceBreakLine(StringUtil.SafeTrim(item["COMMENTS"]));
                    string comments    = prepareStr(orgComments);
                    //額外訊息
                    var ExtInfoList = this.parseExtInfo(orgComments);
                    //DATA_LENGTH
                    int dataLenght = int.Parse(StringUtil.SafeTrim(item["DATA_LENGTH"]));

                    //處理日期轉換欄位
                    if ((("varchar2".Equals(dataType) && dataLenght == 7) || ("nvarchar2".Equals(dataType) && dataLenght == 14)) &&
                        (columnName.ToLower().IndexOf("date") >= 0 || columnName.ToLower().IndexOf("day") >= 0))
                    {
                        tbModelContent.AppendLine("        /// <summary>");
                        tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": 西元日期轉換擴充欄位");
                        tbModelContent.AppendLine("        /// </summary>");
                        //DisplayName
                        tbModelContent.AppendLine("        [DisplayName(\"" + (StringUtil.IsEmpty(comments) ? "未設定" : comments) + "\")]");
                        tbModelContent.AppendLine("        public string " + columnName + "_AD ");
                        tbModelContent.AppendLine("        {");
                        tbModelContent.AppendLine("            get { return HelperUtil.DateTimeToString(TesnUtil.TransTwToDateTime(this." + columnName + ", \"\")); }");
                        tbModelContent.AppendLine("            set { this." + columnName + " = HelperUtil.DateTimeToTwString(HelperUtil.TransToDateTime(value), \"\"); }");
                        tbModelContent.AppendLine("        }");
                        tbModelContent.AppendLine("");
                    }

                    //電話
                    if (ExtInfoList.IndexOf("PHONE") >= 0)
                    {
                        tbModelContent.AppendLine("        /// <summary>");
                        tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": 電話號碼 擴充資料欄位");
                        tbModelContent.AppendLine("        /// </summary>");
                        tbModelContent.AppendLine("        public PhoneNumberModel " + columnName + "_PHONE ");
                        tbModelContent.AppendLine("        {");
                        tbModelContent.AppendLine("            get { return PhoneNumberModel.Parse(this." + columnName + "); }");
                        tbModelContent.AppendLine("            set { this." + columnName + " = value.ToString(); }");
                        tbModelContent.AppendLine("        }");
                        tbModelContent.AppendLine("");
                    }

                    //手機
                    if (ExtInfoList.IndexOf("MOBILE") >= 0)
                    {
                        tbModelContent.AppendLine("        /// <summary>");
                        tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": 手機號碼 擴充資料欄位");
                        tbModelContent.AppendLine("        /// </summary>");
                        tbModelContent.AppendLine("        public MobileNumberModel " + columnName + "_MOBILE ");
                        tbModelContent.AppendLine("        {");
                        tbModelContent.AppendLine("            get { return MobileNumberModel.Parse(this." + columnName + "); }");
                        tbModelContent.AppendLine("            set { this." + columnName + " = value.ToString(); }");
                        tbModelContent.AppendLine("        }");
                        tbModelContent.AppendLine("");
                    }

                    //增加顯示存放欄位
                    if (ExtInfoList.IndexOf("SHOW_TEXT") >= 0)
                    {
                        tbModelContent.AppendLine("        /// <summary>");
                        tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": 轉文字擴充欄位");
                        tbModelContent.AppendLine("        /// </summary>");
                        tbModelContent.AppendLine("        public string " + columnName + "_SHOW_TEXT { get; set; }");
                        tbModelContent.AppendLine("");
                    }

                    //CHECKBOX
                    foreach (string extInfo in ExtInfoList)
                    {
                        var currExtInfo = (extInfo + "").Trim();

                        if (currExtInfo.IndexOf("CHECKBOX:") >= 0)
                        {
                            var currParams = (currExtInfo + "").Trim().Split(':');
                            if (currParams.Length < 2)
                            {
                                throw new Exception(columnName + "欄位的 【CHECKBOX:】設定錯誤");
                            }

                            tbModelContent.AppendLine("        /// <summary>");
                            tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": CHECKBOX 擴充資料欄位");
                            tbModelContent.AppendLine("        /// </summary>");
                            tbModelContent.AppendLine("        public CheckBoxModel " + columnName + "_CHECKBOX ");
                            tbModelContent.AppendLine("        {");
                            tbModelContent.AppendLine("            get { return new CheckBoxModel(base." + columnName + ", \"" + currParams[1] + "\"); }");
                            tbModelContent.AppendLine("            set { this." + columnName + " = value.Value; }");
                            tbModelContent.AppendLine("        }");
                            tbModelContent.AppendLine("");
                        }
                    }

                    //CHECKBOX
                    foreach (string extInfo in ExtInfoList)
                    {
                        var currExtInfo = (extInfo + "").Trim();

                        if (currExtInfo.StartsWith("ENUM:"))
                        {
                            currExtInfo = currExtInfo.Substring(5);

                            var currParams = (currExtInfo + "").Trim().SplitToList(",");

                            tbModelContent.AppendLine("        /// <summary>");
                            tbModelContent.AppendLine("        /// " + columnName + " " + comments + ": 參數值擴充欄位");
                            tbModelContent.AppendLine("        /// </summary>");
                            tbModelContent.AppendLine("        public enum " + columnName + "_ENUM ");
                            tbModelContent.AppendLine("        {");

                            for (int paramIndex = 0; paramIndex < currParams.Count; paramIndex++)
                            {
                                var parma = currParams[paramIndex];
                                //空白時不處理
                                if (string.IsNullOrEmpty(parma))
                                {
                                    continue;
                                }
                                //分割代號與說明
                                var paramCols = (parma + "").Trim().SplitToList("-");
                                if (paramCols.Count < 2)
                                {
                                    throw new Exception(columnName + "欄位的 【ENUM:】設定錯誤  ex: 【ENUM:A-依選手(個人/組),B-依評審項目】");
                                }

                                for (int colIndex = 0; colIndex < paramCols.Count; colIndex++)
                                {
                                    paramCols[colIndex] = paramCols[colIndex].Trim();
                                    if (paramCols[colIndex].Length == 0)
                                    {
                                        throw new Exception(columnName + "欄位的 【ENUM:】設定錯誤, 項目為空");
                                    }
                                }

                                tbModelContent.AppendLine("            /// <summary>");
                                tbModelContent.AppendLine("            /// " + paramCols[1]);
                                tbModelContent.AppendLine("            /// </summary>");
                                tbModelContent.AppendLine("            " + paramCols[0] + " = " + paramIndex + ((paramIndex < currParams.Count - 1) ? "," : ""));
                                if (paramIndex < currParams.Count - 1)
                                {
                                    tbModelContent.AppendLine("");
                                }
                            }

                            tbModelContent.AppendLine("        }");
                            tbModelContent.AppendLine("");
                        }
                    }
                }
                tbModelContent.AppendLine("    }");
                tbModelContent.AppendLine("}");
                tbModelContent.AppendLine("");

                validatorContent.AppendLine("    }");
                validatorContent.AppendLine("}");
                validatorContent.AppendLine("");

                //輸出 TbModel
                fileUtil.WriteToFile(tbModelContent.ToString(), OUTPUT_PTAH + "/Models/Entities/" + className + ".cs");

                //輸出 Validator
                fileUtil.WriteToFile(validatorContent.ToString(), OUTPUT_PTAH + "/Models/Entities/validator/" + className + "Validator.cs");

                //Console.WriteLine(OUTPUT_PTAH + "/" + className + ".cs");

                //StaticCodeMap.TableName
            }
        }
コード例 #3
0
        //private string _testTable = "";

        /// <summary>
        ///
        /// </summary>
        /// <param name="sourceDb"></param>
        /// <param name="sourceSchema"></param>
        /// <param name="targetDb"></param>
        /// <param name="targetSchema"></param>
        /// <param name="resultFilePath"></param>
        /// <param name="resultFileName"></param>
        public OracleDif(
            OracleDBUtil sourceDb, string sourceSchema, OracleDBUtil targetDb, string targetSchema,
            string resultFilePath, string resultFileName)
        {
            //FileUtil fu = new FileUtil();
            var fu = new StringBuilder();
            var tb = new OracleTableInfo();

            // ==============================================================
            // 取得資料庫的 Schema 資訊
            // ==============================================================
            // 取得來源的table Schema 資料

            Console.WriteLine("取得來源資料庫 Schema..");
            var sourceTableInfoMap = tb.GetAllTable(sourceDb, sourceSchema);

            // System.out.println(new BeanUtil().showContent(sourceTableInfoMap));
            // 取得來源的table Schema 資料
            Console.WriteLine("取得目標資料庫 Schema..");
            var targetTableInfoMap = tb.GetAllTable(targetDb, targetSchema);

            Console.WriteLine("比對中..");

            // ==============================================================
            // 比對缺少的 TABLE
            // ==============================================================
            var firstAddFlag = true;

            foreach (var tableName in sourceTableInfoMap.Keys)
            {
                if (!targetTableInfoMap.ContainsKey(tableName))
                {
                    Console.WriteLine("目標缺少 TABLE :[" + tableName + "]");

                    if (firstAddFlag)
                    {
                        fu.AppendLine("/*==============================================================*/");
                        fu.AppendLine("/* 新增 Table*/");
                        fu.AppendLine("/*==============================================================*/");
                        firstAddFlag = false;
                    }

                    // 產生 create sql
                    var sourceTableInfo = sourceTableInfoMap[tableName];
                    fu.AppendLine(GanCreateSql(targetSchema, tableName, sourceTableInfo.ColumnDataMapList,
                                               sourceTableInfo.PKeySet));
                }
            }

            // ==============================================================
            // 各 table 欄位比對
            // ==============================================================
            foreach (var tableName in sourceTableInfoMap.Keys)
            {
                // 目標無此 table 時跳過
                if (!targetTableInfoMap.ContainsKey(tableName))
                {
                    continue;
                }

                // 取得來源 TableInfo
                var sourceTableInfo = sourceTableInfoMap[tableName];
                // 取得目標 TableInfo
                var targetTableInfo = targetTableInfoMap[tableName];

                // 新增欄位
                var addSql = DiffAddColumn(targetSchema, tableName, sourceTableInfo.ColumnDataMapList,
                                           targetTableInfo.ColumnNameSet);

                // 修改欄位
                var modifySql = DiffModifyColumn(targetSchema, tableName, sourceTableInfo.ColumnDataMapByColName,
                                                 targetTableInfo.ColumnDataMapByColName);

                if (StringUtil.NotEmpty(addSql) || StringUtil.NotEmpty(modifySql))
                {
                    fu.AppendLine("/*==============================================================*/");
                    fu.AppendLine("/* 異動 Table : " + tableName + " */");
                    fu.AppendLine("/*==============================================================*/");
                    fu.AppendLine(addSql);
                    fu.AppendLine(modifySql);
                }
            }

            // ==============================================================
            // 反向比對
            // ==============================================================
            //FileUtil reFu = new FileUtil();
            var reFu = new StringBuilder();

            foreach (var tableName in targetTableInfoMap.Keys)
            {
                // 比對缺少TABLE
                if (!sourceTableInfoMap.ContainsKey(tableName))
                {
                    reFu.AppendLine("--來源缺少 TABLE :[" + tableName + "]");
                    continue;
                }
                // 比對缺少欄位
                // 取得來源 TableInfo
                var sourceTableInfo = sourceTableInfoMap[tableName];
                // 取得目標 TableInfo
                var targetTableInfo = targetTableInfoMap[tableName];

                foreach (var columnName in targetTableInfo.ColumnNameSet)
                {
                    if (!sourceTableInfo.ColumnNameSet.Contains(columnName))
                    {
                        reFu.AppendLine("--來源 TABLE " + tableName + " 缺少欄位 :[" + columnName + "]");
                    }
                }
            }

            if (StringUtil.NotEmpty(fu.ToString()))
            {
                fu.AppendLine("/*==============================================================*/");
                fu.AppendLine("/* 反向比對差異部分 */");
                fu.AppendLine("/*==============================================================*/");
                fu.AppendLine(reFu.ToString());
            }

            //TODO
            //fu.writeToFile(resultFilePath, resultFileName);
        }