From 0d4cc01e9466386e0f94cf6945d235669bd81256 Mon Sep 17 00:00:00 2001 From: xiaochanghai Date: Thu, 7 Nov 2024 15:28:37 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC=E6=AF=94=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/CommonController.cs | 599 +++++++++++++++++- Tiobon.Core.Api/Tiobon.Core.xml | 65 ++ 2 files changed, 663 insertions(+), 1 deletion(-) diff --git a/Tiobon.Core.Api/Controllers/CommonController.cs b/Tiobon.Core.Api/Controllers/CommonController.cs index 0e1991b9..77b979dd 100644 --- a/Tiobon.Core.Api/Controllers/CommonController.cs +++ b/Tiobon.Core.Api/Controllers/CommonController.cs @@ -1,4 +1,9 @@ -using Newtonsoft.Json.Linq; +using Confluent.Kafka; +using Newtonsoft.Json.Linq; +using System.Data; +using System.Net; +using Tiobon.Core.Common.DB.Dapper; +using Tiobon.Core.Common.DB.Dapper.DBManager; namespace Tiobon.Core.Controllers; @@ -169,4 +174,596 @@ public class CommonController : BaseApiController } #endregion + + + [HttpGet, AllowAnonymous, Route("Compare")] + public IActionResult Download(Guid id) + { + + StringBuilder sb = new StringBuilder(); + DBServerProvider.SetConnection("defalut1", "Data Source=47.99.54.186;User ID=GHR;Password=Tiobon20190101;Database=Ghr5_MekTec;Encrypt=True;TrustServerCertificate=True;"); + string sql = @"SELECT A.name AS COLUMN_NAME, + B.name TABLE_NAME, + C.value AS column_description, + C.[name], + D.NUMERIC_PRECISION, + D.NUMERIC_SCALE, + D.IS_NULLABLE, + D.data_type COLUMN_TYPE, + E.name AS ConstraintName, + E.definition AS COLUMN_DEFAULT +FROM sys.columns A + LEFT JOIN sys.tables B ON A.object_id = B.object_id + LEFT JOIN sys.extended_properties C + ON C.major_id = A.object_id AND C.minor_id = A.column_id + LEFT JOIN information_schema.columns D + ON D.column_name = A.name AND D.TABLE_NAME = B.[name] + LEFT JOIN sys.default_constraints E + ON E.parent_object_id = A.object_id + AND E.parent_column_id = A.column_id"; + + #region step 1.1 加载表结构 + // 源数据库 + DataTable dt = DbAccess.GetDataTable(sql); + var srcCloumns = + dt + .AsEnumerable() + .Select(o => new CompareStructureCloumn + { + TableName = o.Field("TABLE_NAME"), + ColumnName = o.Field("COLUMN_NAME"), + DefaultValue = o.Field("COLUMN_DEFAULT"), + Null = o.Field("IS_NULLABLE"), + DataType = o.Field("COLUMN_TYPE"), + //Key = o.Field("COLUMN_KEY"), + //Collsion = o.Field("COLLATION_NAME"), + //CharacterSet = o.Field("CHARACTER_SET_NAME") + }) + .ToList(); + Console.WriteLine("", $"加载源数据库[hdis_compare]信息完毕:共有表{srcCloumns.Select(o => o.TableName).Distinct().Count()} 字段 {srcCloumns.Count}"); + + // 目标数据库 + dt = DBServerProvider.GetSqlDapper("defalut1").GetDataTable(sql); + var desrcCloumns = + dt + .AsEnumerable() + .Select(o => new CompareStructureCloumn + { + TableName = o.Field("TABLE_NAME"), + ColumnName = o.Field("COLUMN_NAME"), + DefaultValue = o.Field("COLUMN_DEFAULT"), + Null = o.Field("IS_NULLABLE"), + DataType = o.Field("COLUMN_TYPE"), + //Key = o.Field("COLUMN_KEY"), + //Collsion = o.Field("COLLATION_NAME"), + //CharacterSet = o.Field("CHARACTER_SET_NAME") + }) + .ToList(); + Console.WriteLine("", $"加载目标数据库[hdis]信息完毕:共有表{desrcCloumns.Select(o => o.TableName).Distinct().Count()} 字段 {desrcCloumns.Count}"); + + // #region 1.2 加载外键 + // sql = @"SELECT T.TABLE_NAME, T.CONSTRAINT_NAME, T.CONSTRAINT_TYPE, K.COLUMN_NAME, K.REFERENCED_TABLE_NAME, K.REFERENCED_COLUMN_NAME + //FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS T + //JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K ON T.CONSTRAINT_SCHEMA = K.CONSTRAINT_SCHEMA AND T.TABLE_NAME = K.TABLE_NAME AND T.CONSTRAINT_NAME = K.CONSTRAINT_NAME + //JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON T.CONSTRAINT_SCHEMA = R.CONSTRAINT_SCHEMA AND T.TABLE_NAME = R.TABLE_NAME AND T.CONSTRAINT_NAME = R.CONSTRAINT_NAME + //WHERE R.CONSTRAINT_SCHEMA = '{0}' AND T.CONSTRAINT_TYPE <> 'PRIMARY KEY';"; + + // // 源数据库 + // dt = MySqlHelper.ExecuteDataset(m_ConnStr, string.Format(sql, "hdis_compare")).Tables[0]; + // List srcConstraints = dt + // .AsEnumerable() + // .Select(m => new TableConstraint() + // { + // TABLE_NAME = m.Field(nameof(TableConstraint.TABLE_NAME)), + // CONSTRAINT_NAME = m.Field(nameof(TableConstraint.CONSTRAINT_NAME)), + // CONSTRAINT_TYPE = m.Field(nameof(TableConstraint.CONSTRAINT_TYPE)), + // COLUMN_NAME = m.Field(nameof(TableConstraint.COLUMN_NAME)), + // REFERENCED_TABLE_NAME = m.Field(nameof(TableConstraint.REFERENCED_TABLE_NAME)), + // REFERENCED_COLUMN_NAME = m.Field(nameof(TableConstraint.REFERENCED_COLUMN_NAME)) + // }) + // .ToList(); + // Console.WriteLine("", $"加载源数据库[hdis_compare]外键完毕:共有外键 {srcConstraints.Count} 条"); + + // // 目标据库 + // dt = MySqlHelper.ExecuteDataset(m_ConnStr, string.Format(sql, "hdis")).Tables[0]; + // List destConstraints = dt + // .AsEnumerable() + // .Select(m => new TableConstraint() + // { + // TABLE_NAME = m.Field(nameof(TableConstraint.TABLE_NAME)), + // CONSTRAINT_NAME = m.Field(nameof(TableConstraint.CONSTRAINT_NAME)), + // CONSTRAINT_TYPE = m.Field(nameof(TableConstraint.CONSTRAINT_TYPE)), + // COLUMN_NAME = m.Field(nameof(TableConstraint.COLUMN_NAME)), + // REFERENCED_TABLE_NAME = m.Field(nameof(TableConstraint.REFERENCED_TABLE_NAME)), + // REFERENCED_COLUMN_NAME = m.Field(nameof(TableConstraint.REFERENCED_COLUMN_NAME)) + // }) + // .ToList(); + // Console.WriteLine("", $"加载目标数据库[hdis]外键完毕:共有外键 {destConstraints.Count} 条"); + // #endregion + + // #region 1.3 加载索引 + // sql = @"SELECT TABLE_NAME, NON_UNIQUE, INDEX_NAME, COLUMN_NAME, INDEX_TYPE + //FROM INFORMATION_SCHEMA.STATISTICS + //WHERE TABLE_SCHEMA = '{0}' AND INDEX_NAME <> 'PRIMARY';"; + // // 源数据库 + // dt = MySqlHelper.ExecuteDataset(m_ConnStr, string.Format(sql, "hdis_compare")).Tables[0]; + // List srcIndexes = dt + // .AsEnumerable() + // .Select(m => new TableIndex() + // { + // TABLE_NAME = m.Field(nameof(TableIndex.TABLE_NAME)), + // NON_UNIQUE = m.Field(nameof(TableIndex.NON_UNIQUE)), + // INDEX_NAME = m.Field(nameof(TableIndex.INDEX_NAME)), + // COLUMN_NAME = m.Field(nameof(TableIndex.COLUMN_NAME)), + // INDEX_TYPE = m.Field(nameof(TableIndex.INDEX_TYPE)) + // }) + // .ToList(); + // SenConsole.WriteLinedLog("", $"加载源数据库[hdis_compare]索引完毕:共有索引 {srcConstraints.Count} 条"); + + // // 源数据库 + // dt = MySqlHelper.ExecuteDataset(m_ConnStr, string.Format(sql, "hdis")).Tables[0]; + // List destIndexes = dt + // .AsEnumerable() + // .Select(m => new TableIndex() + // { + // TABLE_NAME = m.Field(nameof(TableIndex.TABLE_NAME)), + // NON_UNIQUE = m.Field(nameof(TableIndex.NON_UNIQUE)), + // INDEX_NAME = m.Field(nameof(TableIndex.INDEX_NAME)), + // COLUMN_NAME = m.Field(nameof(TableIndex.COLUMN_NAME)), + // INDEX_TYPE = m.Field(nameof(TableIndex.INDEX_TYPE)) + // }) + // .ToList(); + // Console.WriteLine("", $"加载目标数据库[hdis]索引完毕:共有索引 {srcConstraints.Count} 条"); + // #endregion + + + + + #endregion + + + + #region step 2 比对数据库结构 + Console.WriteLine("", "开始比较数据库结构"); + #region 2.1 比较字段 + var sExcept = srcCloumns.Except(desrcCloumns, new CompareStructureCloumnComparer()).ToList(); + var dExcept = desrcCloumns.Except(srcCloumns, new CompareStructureCloumnComparer()).ToList(); + var except = new List(); + dExcept.ForEach(o => + { + bool has = false; + sExcept.ForEach(p => + { + //具有相同的两个重复记录 + if (o.TableName == p.TableName && o.ColumnName == p.ColumnName) + { + has = true; + return; + } + }); + if (!has) + { + except.Add(o); + } + }); + except = except.Union(sExcept).ToList(); + Console.WriteLine("", "字段比较完毕"); + if (except.Count <= 0) + { + Console.WriteLine("", "数据结构完全一致"); + return Ok("数据结构完全一致"); + } + #endregion + + #region 2.2 生成需要创建的表 + bool b_hasConetnt = false; + sb.AppendLine("SET FOREIGN_KEY_CHECKS = 0;\r\n"); + var temp = except.Select(o => o.TableName).Distinct(); + Console.WriteLine("", $"字段不同数量为 {except.Count}"); + var sTempNames = srcCloumns.Select(o => o.TableName); + var dTempNames = desrcCloumns.Select(o => o.TableName); + + var createTablesNames = temp.Where(o => !dTempNames.Contains(o)).ToList(); + Console.WriteLine("", $"生成需要创建的表 数量 {createTablesNames.Count}"); + if (createTablesNames.Any()) + { + createTablesNames.ForEach(tname => + { + + string sql1 = @$"DECLARE @TableName NVARCHAR(128) = '{tname}'; +DECLARE @SQL NVARCHAR(MAX); + +-- 获取表的创建语句 +SET @SQL = 'CREATE TABLE ' + @TableName + ' (' + CHAR(13) + CHAR(10); + +-- 获取列信息 +SELECT @SQL = @SQL + + ' ' + c.name + ' ' + + t.name + + CASE + WHEN t.name IN ('nvarchar', 'varchar', 'char', 'nchar') THEN '(' + CAST(c.max_length AS NVARCHAR(10)) + ')' + WHEN t.name IN ('decimal', 'numeric') THEN '(' + CAST(c.precision AS NVARCHAR(10)) + ', ' + CAST(c.scale AS NVARCHAR(10)) + ')' + ELSE '' + END + + CASE + WHEN c.is_nullable = 0 THEN ' NOT NULL' + ELSE ' NULL' + END + + CASE + WHEN ep.value IS NOT NULL THEN ' -- ' + CAST(ep.value AS NVARCHAR(MAX)) + ELSE '' + END + ',' + CHAR(13) + CHAR(10) +FROM + sys.columns c +INNER JOIN + sys.types t ON c.user_type_id = t.user_type_id +LEFT JOIN + sys.extended_properties ep ON ep.major_id = c.object_id AND ep.minor_id = c.column_id AND ep.class = 1 +WHERE + c.object_id = OBJECT_ID(@TableName); + +-- 移除最后一个逗号 +SET @SQL = LEFT(@SQL, LEN(@SQL) - 2); + +-- 添加主键信息 +SELECT @SQL = @SQL + CHAR(13) + CHAR(10) + + ' CONSTRAINT PK_' + @TableName + ' PRIMARY KEY (' + + COL_NAME(ic.object_id, ic.column_id) + ')' + CHAR(13) + CHAR(10) + + ')' +FROM + sys.indexes i +INNER JOIN + sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id +WHERE + i.object_id = OBJECT_ID(@TableName) AND i.is_primary_key = 1; + +-- 输出生成的 SQL 语句 +select @SQL SQL ;"; + DataTable ds = DbAccess.GetDataTable(sql1); + if (ds.Rows.Count > 0) + { + b_hasConetnt = true; + sb.AppendLine($"{ds.Rows[0]["SQL"].ToString()};\r\n"); + Console.WriteLine("", $"生成表[{tname}]结构语句"); + } + else + { + Console.WriteLine("", $"生成表[{tname}]结构语句异常,表不存在"); + } + }); + Console.WriteLine("", $"生成需要创建的表完毕"); + } + + #endregion + + #region 2.3 生成需要删除的表 + var deleteTablesNames = temp.Where(o => !sTempNames.Contains(o)).ToList(); + Console.WriteLine("", $"生成需要删除的表 数量 {deleteTablesNames.Count}"); + if (deleteTablesNames.Any()) + { + deleteTablesNames.ForEach(tname => + { + b_hasConetnt = true; + sb.AppendLine($"DROP TABLE `{tname}`;\r\n"); + Console.WriteLine("", $"生成表[{tname}]删除语句"); + }); + Console.WriteLine("", $"生成需要删除的表完毕"); + } + + #endregion + + #region 2.4 生成需要修改的表 + var deletedColumns = new List<(string table, string column)>(); + var alterTablesNames = temp.Where(o => dTempNames.Contains(o) && sTempNames.Contains(o)).ToList(); + Console.WriteLine("", $"生成需要修改的表 数量 {alterTablesNames.Count}"); + if (alterTablesNames.Any()) + { + alterTablesNames.ForEach(o => + { + #region 2.4.1 创建列语句 + except + .Where(t => t.TableName == o && !desrcCloumns.Where(p => p.TableName == o).Select(p => p.ColumnName).ToList().Contains(t.ColumnName)) + .ToList() + .ForEach(t => + { + b_hasConetnt = true; + //sb.AppendLine($"ALTER TABLE `hdis`.`{t.TableName}`" + + // $" ADD COLUMN `{t.ColumnName}` {t.DataType}{GetCharacter_Set_Name(t.CharacterSet)}{GetCollate(t.Collsion)}{GetNull(t.Null)}{GetDefaultValue(t.DefaultValue, t.DataType)};\r\n"); + + sb.AppendLine($"ALTER TABLE [{t.TableName}] ADD [{t.ColumnName}] {t.DataType} NULL"); + //ALTER TABLE[dbo].[Ghre_StudyRule] ADD[Column_42] int NOT NULL DEFAULT 1 + }); + #endregion + + #region 2.4.2 删除列语句 + except + .Where(t => t.TableName == o && !srcCloumns.Where(p => p.TableName == o).Select(p => p.ColumnName).ToList().Contains(t.ColumnName)) + .ToList() + .ForEach(t => + { + if (t.ColumnName == "deleted") // 如果添加删除列 deleted,生成删除垃圾数据的语句 + { + sb.AppendLine($"/* 删除垃圾数据 */"); + sb.AppendLine($"DELETE FROM hdis.{t.TableName} WHERE deleted = 1;"); + } + //string forignKey = QueryForignKeyProduct("hdis", tableName: o, colName: t.ColumnName); + //string indexs = QueryIndexProduct("hdis", tableName: o, colName: t.ColumnName); + //b_hasConetnt = true; + //if (!string.IsNullOrEmpty(forignKey)) sb.AppendLine(forignKey); + //if (!string.IsNullOrEmpty(indexs)) sb.AppendLine(indexs); + + sb.AppendLine($"ALTER TABLE [dbo].[`{t.TableName}`] DROP COLUMN `{t.ColumnName}`;\r\n"); + //ALTER TABLE [dbo].[Ghre_StudyRule] DROP COLUMN [IsDeptLower] + deletedColumns.Add((t.TableName, t.ColumnName)); + }); + #endregion + + #region 2.4.3 修改列语句 + //except + //.Where(t => t.TableName == o && srcCloumns.Where(p => p.TableName == o).Select(p => p.ColumnName).ToList().Contains(t.ColumnName) + // && desrcCloumns.Where(p => p.TableName == o).Select(p => p.ColumnName).ToList().Contains(t.ColumnName)) + // .ToList() + //.ForEach(t => + //{ + // b_hasConetnt = true; + // string renovate = RenovateNotNull("hdis", t.TableName, t.ColumnName, t.Null, t.DefaultValue, t.DataType); + // sb.AppendLine(renovate); + // sb.AppendLine($"ALTER TABLE `hdis`.`{t.TableName}` CHANGE `{t.ColumnName}` `{t.ColumnName}` {t.DataType}{GetCharacter_Set_Name(t.CharacterSet)}{GetCollate(t.Collsion)}{GetNull(t.Null)}{GetDefaultValue(t.DefaultValue, t.DataType)};\r\n"); + //}); + #endregion + }); + Console.WriteLine("", $"生成需要删除的表完毕"); + } + else + { + Console.WriteLine("", $"没有需要修改的表"); + } + + #endregion + + #region 2.5 外键 + //int newConstraintCount = 0; + //foreach (var constraint in srcConstraints) + //{ + // if (createTablesNames.Contains(constraint.TABLE_NAME)) + // { + // continue; + // } + // if (deletedColumns.Contains((constraint.TABLE_NAME, constraint.COLUMN_NAME))) + // { + // continue; + // } + // if (!destConstraints.Any(x => x.CONSTRAINT_NAME == constraint.CONSTRAINT_NAME + // && x.TABLE_NAME == constraint.TABLE_NAME && x.COLUMN_NAME == constraint.COLUMN_NAME + // && x.REFERENCED_TABLE_NAME == constraint.REFERENCED_TABLE_NAME && x.REFERENCED_COLUMN_NAME == constraint.REFERENCED_COLUMN_NAME)) + // { + // newConstraintCount++; + // sb.AppendLine($"ALTER TABLE `hdis`.`{constraint.TABLE_NAME}` ADD CONSTRAINT `{constraint.CONSTRAINT_NAME}` FOREIGN KEY(`{constraint.COLUMN_NAME}`) REFERENCES `{constraint.REFERENCED_TABLE_NAME}` (`{constraint.REFERENCED_COLUMN_NAME}`);"); + // } + //} + //if (newConstraintCount > 0) + //{ + // b_hasConetnt = true; + // Console.WriteLine("", $"生成需要添加的外键 数量 {newConstraintCount}"); + // sb.AppendLine(); + //} + //else + //{ + // Console.WriteLine("", $"没有需要添加的外键"); + //} + //int removeConstraintCount = 0; + //foreach (var constraint in destConstraints) + //{ + // if (deletedColumns.Contains((constraint.TABLE_NAME, constraint.COLUMN_NAME))) + // { + // continue; + // } + // if (!srcConstraints.Any(x => x.CONSTRAINT_NAME == constraint.CONSTRAINT_NAME + // && x.TABLE_NAME == constraint.TABLE_NAME && x.COLUMN_NAME == constraint.COLUMN_NAME + // && x.REFERENCED_TABLE_NAME == constraint.REFERENCED_TABLE_NAME && x.REFERENCED_COLUMN_NAME == constraint.REFERENCED_COLUMN_NAME)) + // { + // removeConstraintCount++; + // sb.AppendLine($"ALTER TABLE `hdis`.`{constraint.TABLE_NAME}` DROP FOREIGN KEY `{constraint.CONSTRAINT_NAME}`;"); + // } + //} + //if (removeConstraintCount > 0) + //{ + // b_hasConetnt = true; + // Console.WriteLine("", $"生成需要删除的外键 数量 {removeConstraintCount}"); + // sb.AppendLine(); + //} + //else + //{ + // Console.WriteLine("", $"没有需要删除的外键"); + //} + //lock (m_LockProgressBar) + //{ + // m_PBValue = 5; + //} + #endregion + + #region 2.6 索引 + //int newIndexCount = 0; + //foreach (var index in srcIndexes) + //{ + // if (createTablesNames.Contains(index.TABLE_NAME)) + // { + // continue; + // } + // if (deletedColumns.Contains((index.TABLE_NAME, index.COLUMN_NAME))) + // { + // continue; + // } + // if (!destIndexes.Any(x => x.INDEX_NAME == index.INDEX_NAME + // && x.TABLE_NAME == index.TABLE_NAME && x.COLUMN_NAME == index.COLUMN_NAME + // && x.NON_UNIQUE == index.NON_UNIQUE && x.INDEX_TYPE == index.INDEX_TYPE)) + // { + // newIndexCount++; + // if (index.NON_UNIQUE == 0) + // { + // sb.AppendLine($"ALTER TABLE `hdis`.`{index.TABLE_NAME}` ADD UNIQUE INDEX `{index.INDEX_NAME}` (`{index.COLUMN_NAME}`);"); + // } + // else if (index.INDEX_TYPE == "FULLTEXT") + // { + // sb.AppendLine($"ALTER TABLE `hdis`.`{index.TABLE_NAME}` ADD FULLTEXT INDEX `{index.INDEX_NAME}` (`{index.COLUMN_NAME}`) USING {index.INDEX_TYPE};"); + // } + // else if (index.INDEX_TYPE == "SPATIAL") + // { + // sb.AppendLine($"ALTER TABLE `hdis`.`{index.TABLE_NAME}` ADD SPATIAL INDEX `{index.INDEX_NAME}` (`{index.COLUMN_NAME}`) USING {index.INDEX_TYPE};"); + // } + // else + // { + // sb.AppendLine($"ALTER TABLE `hdis`.`{index.TABLE_NAME}` ADD INDEX `{index.INDEX_NAME}` (`{index.COLUMN_NAME}`) USING {index.INDEX_TYPE};"); + // } + // } + //} + //if (newIndexCount > 0) + //{ + // b_hasConetnt = true; + // Console.WriteLine("", $"生成需要添加的索引 数量 {newIndexCount}"); + // sb.AppendLine(); + //} + //else + //{ + // Console.WriteLine("", $"没有需要添加的索引"); + //} + //int removeIndexCount = 0; + //foreach (var index in destIndexes) + //{ + // if (deletedColumns.Contains((index.TABLE_NAME, index.COLUMN_NAME))) + // { + // continue; + // } + // if (!srcIndexes.Any(x => x.INDEX_NAME == index.INDEX_NAME + // && x.TABLE_NAME == index.TABLE_NAME && x.COLUMN_NAME == index.COLUMN_NAME + // && x.NON_UNIQUE == index.NON_UNIQUE && x.INDEX_TYPE == index.INDEX_TYPE)) + // { + // removeIndexCount++; + // sb.AppendLine($"ALTER TABLE `hdis`.`{index.TABLE_NAME}` DROP INDEX `{index.INDEX_NAME}`;"); + // } + //} + //if (removeIndexCount > 0) + //{ + // b_hasConetnt = true; + // Console.WriteLine("", $"生成需要删除的索引 数量 {removeIndexCount}"); + // sb.AppendLine(); + //} + //else + //{ + // Console.WriteLine("", $"没有需要删除的索引"); + //} + //lock (m_LockProgressBar) + //{ + // m_PBValue = 6; + //} + #endregion + + //sb.AppendLine("SET FOREIGN_KEY_CHECKS = 1;\r\n"); + + if (b_hasConetnt) + { + Console.WriteLine("", "比较数据库结构完毕"); + } + else + { + Console.WriteLine("", "比较数据库结构完毕,数据结构完全一致"); + } + #endregion + + FileHelper.WriteFile("C:/" + Guid.NewGuid() + ".sql", sb.ToString()); + return Ok(sb.ToString()); + //string sql = "SELECT * FROM FileAttachment where ID='{0}' and IsDeleted='false'"; + + + //if (attachment != null) + //{ + // var fileName = attachment.FileName; + // string path = "wwwroot/" + attachment.Path + fileName; + // FileStream fs = new FileStream(path, FileMode.OpenOrCreate); + // fs.Close(); + // return File(new FileStream(path, FileMode.Open), "application/octet-stream", fileName); + //} + //else + //{ + // return Ok("无效ID"); + //} + + } + + + #region 表信息 + /// + /// 表信息 + /// + public class CompareStructureCloumn + { + /// + /// 表名称 + /// + public string TableName { set; get; } + /// + /// 字段名称 + /// + public string ColumnName { set; get; } + /// + /// 数据类型 + /// + public string DataType { set; get; } + /// + /// 字符集 + /// + public string CharacterSet { set; get; } + /// + /// + /// + public string Collsion { set; get; } + /// + /// 是否为空 + /// + public string Null { set; get; } + /// + /// 默认值 + /// + public string DefaultValue { set; get; } + /// + /// 键 + /// + public string Key { set; get; } + + } + #endregion + + + + #region 自定义比对器 + /// + /// 自定义比对器 + /// + public class CompareStructureCloumnComparer : IEqualityComparer + { + /// + /// 比对规则 + /// + /// + /// + /// + public bool Equals(CompareStructureCloumn x, CompareStructureCloumn y) + { + var b = x.TableName == y.TableName && x.ColumnName == y.ColumnName + && x.CharacterSet == y.CharacterSet && (x.Collsion == y.Collsion) + && x.DataType == y.DataType && x.DefaultValue == y.DefaultValue + && x.Key == y.Key && x.Null == y.Null; + return b; + } + /// + /// + /// + /// + /// + public int GetHashCode(CompareStructureCloumn obj) + { + return obj.ToString().GetHashCode(); + } + } + #endregion } \ No newline at end of file diff --git a/Tiobon.Core.Api/Tiobon.Core.xml b/Tiobon.Core.Api/Tiobon.Core.xml index 5ca35530..d0a0f92c 100644 --- a/Tiobon.Core.Api/Tiobon.Core.xml +++ b/Tiobon.Core.Api/Tiobon.Core.xml @@ -325,6 +325,71 @@ + + + 表信息 + + + + + 表名称 + + + + + 字段名称 + + + + + 数据类型 + + + + + 字符集 + + + + + + + + + + 是否为空 + + + + + 默认值 + + + + + 键 + + + + + 自定义比对器 + + + + + 比对规则 + + + + + + + + + + + + 构造函数