/// <summary>检查字段改变。某些数据库(如SQLite)没有添删改字段的DDL语法,可重载该方法,使用重建表方法ReBuildTable</summary> /// <param name="entitytable"></param> /// <param name="dbtable"></param> /// <param name="onlySql"></param> /// <param name="noDelete"></param> /// <returns></returns> protected virtual String CheckColumnsChange(IDataTable entitytable, IDataTable dbtable, Boolean onlySql, Boolean noDelete) { //var onlySql = mode <= Migration.ReadOnly; //var noDelete = mode < Migration.Full; var sb = new StringBuilder(); var etdic = entitytable.Columns.ToDictionary(e => e.ColumnName.ToLower(), e => e, StringComparer.OrdinalIgnoreCase); var dbdic = dbtable.Columns.ToDictionary(e => e.ColumnName.ToLower(), e => e, StringComparer.OrdinalIgnoreCase); #region 新增列 foreach (var item in entitytable.Columns) { if (!dbdic.ContainsKey(item.ColumnName.ToLower())) { // 非空字段需要重建表 if (!item.Nullable) { //var sql = ReBuildTable(entitytable, dbtable); //if (noDelete) //{ // WriteLog("数据表新增非空字段[{0}],需要重建表,请手工执行:\r\n{1}", item.Name, sql); // return sql; //} //Database.CreateSession().Execute(sql); //return String.Empty; // 非空字段作为可空字段新增,避开重建表 item.Nullable = true; } PerformSchema(sb, onlySql, DDLSchema.AddColumn, item); if (!item.Description.IsNullOrEmpty()) { PerformSchema(sb, onlySql, DDLSchema.AddColumnDescription, item); } } } #endregion #region 除列 var sbDelete = new StringBuilder(); for (var i = dbtable.Columns.Count - 1; i >= 0; i--) { var item = dbtable.Columns[i]; if (!etdic.ContainsKey(item.ColumnName.ToLower())) { if (!String.IsNullOrEmpty(item.Description)) { PerformSchema(sb, onlySql || noDelete, DDLSchema.DropColumnDescription, item); } PerformSchema(sbDelete, onlySql || noDelete, DDLSchema.DropColumn, item); } } if (sbDelete.Length > 0) { if (noDelete) { // 不许删除列,显示日志 WriteLog("数据表中发现有多余字段,请手工执行以下语句删除:" + Environment.NewLine + sbDelete); } else { if (sb.Length > 0) { sb.AppendLine(";"); } sb.Append(sbDelete); } } #endregion #region 修改列 // 开发时的实体数据库 var entityDb = DbFactory.Create(entitytable.DbType); foreach (var item in entitytable.Columns) { if (!dbdic.TryGetValue(item.ColumnName, out var dbf)) { continue; } if (IsColumnTypeChanged(item, dbf)) { WriteLog("字段{0}.{1}类型需要由数据库的{2}改变为实体的{3}", entitytable.Name, item.Name, dbf.DataType, item.DataType); PerformSchema(sb, noDelete, DDLSchema.AlterColumn, item, dbf); } if (IsColumnChanged(item, dbf, entityDb)) { PerformSchema(sb, noDelete, DDLSchema.AlterColumn, item, dbf); } //if (item.Description + "" != dbf.Description + "") if (FormatDescription(item.Description) != FormatDescription(dbf.Description)) { // 先删除旧注释 //if (dbf.Description != null) PerformSchema(sb, noDelete, DDLSchema.DropColumnDescription, dbf); // 加上新注释 if (!item.Description.IsNullOrEmpty()) { PerformSchema(sb, onlySql, DDLSchema.AddColumnDescription, item); } } } #endregion return(sb.ToString()); }
/// <summary>检查字段改变。某些数据库(如SQLite)没有添删改字段的DDL语法,可重载该方法,使用重建表方法ReBuildTable</summary> /// <param name="entitytable"></param> /// <param name="dbtable"></param> /// <param name="setting"></param> /// <returns></returns> protected virtual String CheckColumnsChange(IDataTable entitytable, IDataTable dbtable, NegativeSetting setting) { #region 准备工作 var onlySql = setting.CheckOnly; var sql = String.Empty; var sb = new StringBuilder(); var entitydic = new Dictionary <String, IDataColumn>(StringComparer.OrdinalIgnoreCase); if (entitytable.Columns != null) { foreach (var item in entitytable.Columns) { if (entitydic.ContainsKey(item.ColumnName.ToLower())) { WriteLog("《" + entitytable.Name + "》实体中存在重复列名,请检查《" + entitytable.TableName + "》表《" + item.Name + "》属性的ColumnName配置(目前配置为:" + item.ColumnName + ")。"); continue; } entitydic.Add(item.ColumnName.ToLower(), item); } } var dbdic = new Dictionary <String, IDataColumn>(StringComparer.OrdinalIgnoreCase); if (dbtable.Columns != null) { foreach (var item in dbtable.Columns) { dbdic.Add(item.ColumnName.ToLower(), item); } } #endregion #region 新增列 foreach (IDataColumn item in entitytable.Columns) { if (!dbdic.ContainsKey(item.ColumnName.ToLower())) { //AddColumn(sb, item, onlySql); PerformSchema(sb, onlySql, DDLSchema.AddColumn, item); if (!String.IsNullOrEmpty(item.Description)) { PerformSchema(sb, onlySql, DDLSchema.AddColumnDescription, item); } //! 以下已经不需要了,目前只有SQLite会采用重建表的方式添加删除字段。如果这里提前添加了字段,重建表的时候,会导致失败。 //// 这里必须给dbtable加加上当前列,否则下面如果刚好有删除列的话,会导致增加列成功,然后删除列重建表的时候没有新加的列 //dbtable.Columns.Add(item.Clone(dbtable)); } } #endregion #region 除列 var sbDelete = new StringBuilder(); for (Int32 i = dbtable.Columns.Count - 1; i >= 0; i--) { var item = dbtable.Columns[i]; if (!entitydic.ContainsKey(item.ColumnName.ToLower())) { if (!String.IsNullOrEmpty(item.Description)) { PerformSchema(sb, onlySql, DDLSchema.DropColumnDescription, item); } PerformSchema(sbDelete, setting.NoDelete, DDLSchema.DropColumn, item); } } if (sbDelete.Length > 0) { if (setting.NoDelete) { //不许删除列,显示日志 WriteLog("数据表中发现有多余字段,请手工执行以下语句删除:" + Environment.NewLine + sbDelete.ToString()); } else { if (sb.Length > 0) { sb.AppendLine(";"); } sb.Append(sbDelete.ToString()); } } #endregion #region 修改列 // 开发时的实体数据库 var entityDb = DbFactory.Create(entitytable.DbType); foreach (var item in entitytable.Columns) { IDataColumn dbf = null; if (!dbdic.TryGetValue(item.ColumnName, out dbf)) { continue; } if (IsColumnTypeChanged(item, dbf)) { WriteLog("字段{0}.{1}类型需要由{2}改变为{3}", entitytable.Name, item.Name, dbf.DataType, item.DataType); PerformSchema(sb, onlySql, DDLSchema.AlterColumn, item, dbf); } if (IsColumnChanged(item, dbf, entityDb)) { PerformSchema(sb, onlySql, DDLSchema.AlterColumn, item, dbf); } if (IsColumnDefaultChanged(item, dbf, entityDb)) { ChangeColmnDefault(sb, onlySql, item, dbf, entityDb); } if (item.Description + "" != dbf.Description + "") { // 先删除旧注释 //if (!String.IsNullOrEmpty(dbf.Description)) DropColumnDescription(sb, dbf, onlySql); //if (!String.IsNullOrEmpty(dbf.Description)) PerformSchema(sb, onlySql, DDLSchema.DropColumnDescription, dbf); if (dbf.Description != null) { PerformSchema(sb, onlySql, DDLSchema.DropColumnDescription, dbf); } // 加上新注释 if (!String.IsNullOrEmpty(item.Description)) { PerformSchema(sb, onlySql, DDLSchema.AddColumnDescription, item); } } } #endregion return(sb.ToString()); }