private Task <List <SchemaInfoTuple> > LoadSchemaFromFile(String path) { return(Task.Run(() => { return SchemaAssistor.LoadSchemaInfos(path); })); }
private async void _tsmiSaveSchemaToFile_Click(object sender, EventArgs e) { var dialogResult = this._sfdSaveSchema.ShowDialog(); if (dialogResult != DialogResult.OK) { return; } var savePath = this._sfdSaveSchema.FileName; //选择存储路径 //补全结构信息 //序列化到文件中 this.EnableContol(false); try { List <SchemaInfoTuple> schemaInfos = this._schemaInfoTable.Values.ToList(); switch (this.CurrentSchemaLoadType) { case SchemaLoadType.Connection: { //补全所有尚未获取的元数据信息 foreach (var schemaInfo in schemaInfos) { if (schemaInfo.ColumnSchemas == null) { await this.CompleteSchema(schemaInfo); } } } break; case SchemaLoadType.SchemaFile: { } break; } this.ShowTipInformation("正在保存结构信息到文件中..."); try { await Task.Run(() => { SchemaAssistor.SaveSchemaInfos(savePath, schemaInfos); }); String message = "已保存当前的所有结构信息!"; MessageBox.Show(this, message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); this.ShowTipInformation(message); } catch (Exception exc) { this.ShowTipInformation(); MessageBox.Show(this, "保存失败!" + exc.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } finally { this.EnableContol(true); } }
private async void Export() { this.EnableContol(false); try { IList <SchemaInfoTuple> schemaInfos = null; switch (this.CurrentSchemaLoadType) { case SchemaLoadType.Connection: { //补全所有尚未获取的元数据信息 schemaInfos = new List <SchemaInfoTuple>(); foreach (var tableSchema in this.CheckedTableSchemas) { var schemaInfo = this._schemaInfoTable[tableSchema]; if (SchemaAssistor.IsRequiredCompleteSchema(schemaInfo)) { this.ShowTipInformation(String.Format("正在补全 [{0}] 的结构信息...", schemaInfo.ObjectSchema.Name)); await this.CompleteSchema(schemaInfo); } schemaInfos.Add(schemaInfo); } } break; case SchemaLoadType.SchemaFile: { foreach (var tableSchema in this.CheckedTableSchemas) { var schemaInfo = this._schemaInfoTable[tableSchema]; schemaInfos.Add(schemaInfo); } } break; } this.ShowTipInformation("正在导出结构信息..."); //获取所有选择的导出定向器 var targeters = this.GetCheckedExportTargeters(); await Task.Run(() => { this.CurrentSchemaExporter.Export(targeters, schemaInfos, this.CurrentExportConfig); }); String exportCompleted = "导出完成!"; this.ShowTipInformation(exportCompleted); this.ShowDialogTipInformation(exportCompleted); } catch (Exception exc) { this.ShowErrorInformation("导出时发生异常!" + exc.Message); MessageBox.Show(exc.ToString(), Resources.Exception_Title, MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.EnableContol(true); } }
private async Task CompleteSchema(SchemaInfoTuple schemaInfo) { this.ShowTipInformation($"正在补全 [{schemaInfo.ObjectSchema.Name}] 的结构信息..."); await Task.Run(() => { SchemaAssistor.CompleteSchema(this.CurrentSchemaProvider, schemaInfo); }); this.ShowTipInformation(); }
private async Task CompareSchema() { this.ShowTipInformation("正在比较结构的差异..."); try { List <SchemaDifferenceInfo> differenceInfos = null; try { differenceInfos = await Task.Run(() => SchemaAssistor.CompareSchemaInfo(this.SourceSchemaInfos, this.TargetSchemaInfos)); } catch (Exception exc) { MessageBox.Show(this, "获取信息差异时发生错误!" + exc.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } this.ShowTipInformation("正在准备差异数据..."); this.ObjectSchemaDifferenceTable = differenceInfos.ToDictionary(t => t.Schema, t => t.DifferenceType); //从源中获取目标结构中没有的信息 var targetSchemaTable = this.TargetSchemaInfos.ToDictionary(t => t.ObjectSchema.Name); foreach (var schema in this.SourceSchemaInfos) { if (!targetSchemaTable.ContainsKey(schema.ObjectSchema.Name)) { this.TargetSchemaInfos.Add(schema); } } try { this.RenderingSchemaTree(this.SourceSchemaInfos, this._tvSourceSchema, false); this.RenderingSchemaTree(this.TargetSchemaInfos, this._tvTargetSchema, true); } catch (Exception exc) { MessageBox.Show(this, "绘制差异时发生错误!" + exc.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } } catch (Exception exc) { MessageBox.Show(this, "比较差异信息时发生错误!" + exc.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); } finally { this.ShowTipInformation(); } }
private async void _btnCompare_Click(object sender, EventArgs e) { if (this._schemaInfoTable.Count <= 0) { this.CanContinue = false; MessageBox.Show(this, "当前尚未加载结构信息!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } this.EnableContol(false); try { //补全所有尚未获取的元数据信息 IList <SchemaInfoTuple> schemaInfos = this._schemaInfoTable.Values.ToList(); foreach (var schemaInfo in schemaInfos) { if (SchemaAssistor.IsRequiredCompleteSchema(schemaInfo)) { this.ShowTipInformation(String.Format("正在补全 [{0}] 的结构信息...", schemaInfo.ObjectSchema.Name)); await this.CompleteSchema(schemaInfo); } } var dialogResult = MessageBox.Show(this, "信息补全完成,是否开始比较?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dialogResult != DialogResult.Yes) { return; } this.CanContinue = true; this.Close(); } catch (Exception exc) { this.CanContinue = false; MessageBox.Show(this, "补全目标结构信息时发生异常,操作已停止!" + exc.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { this.EnableContol(true); } }
private async void _tvSchema_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { if (_isLoadingColumnSchema) { return; } this._isLoadingColumnSchema = true; this._tvSchema.Enabled = false; try { var node = e.Node; if (node.Parent != null) { var schemaData = e.Node.Tag as IObjectSchema; var schemaInfo = this._schemaInfoTable[schemaData]; if (SchemaAssistor.IsRequiredCompleteSchema(schemaInfo)) { _waitColumnSchemaLoad.IsRolled = true; _waitColumnSchemaLoad.Visible = true; try { await this.CompleteSchema(schemaInfo); } finally { _waitColumnSchemaLoad.IsRolled = false; _waitColumnSchemaLoad.Visible = false; } } switch (schemaInfo.SchemaType) { case SchemaType.Table: { this._tabSchemaShow.SelectedTab = this._pageColumnSchema; this._pnlSchemaDefine.Visible = false; this._pnlColumnSchema.Visible = true; this._dgvColumnSchema.DataSource = schemaInfo.ColumnSchemas; this._dgvIndexColumnSchema.DataSource = schemaInfo.IndexColumnSchemas; } break; case SchemaType.View: { this._pnlColumnSchema.Visible = true; this._pnlSchemaDefine.Visible = false; this._tabSchemaShow.SelectedTab = this._pageColumnSchema; this._dgvColumnSchema.DataSource = schemaInfo.ColumnSchemas; this._dgvIndexColumnSchema.DataSource = null; } break; case SchemaType.Procedure: { this._pnlColumnSchema.Visible = false; this._pnlSchemaDefine.Visible = true; this._tabSchemaShow.SelectedTab = this._pageDefine; this._richTbSchemaDefine.Text = ((ProcedureSchema)schemaData).Definition; } break; case SchemaType.Function: { this._pnlColumnSchema.Visible = false; this._pnlSchemaDefine.Visible = true; this._tabSchemaShow.SelectedTab = this._pageDefine; this._richTbSchemaDefine.Text = ((FunctionSchema)schemaData).Definition; } break; } } } finally { _isLoadingColumnSchema = false; this._tvSchema.Enabled = true; } }
private async void CompareSchema(SchemaCompareTargetType targetType) { if (this.IsBusyingState(true)) { return; } this.EnableContol(false); this.EnterBusyingState(); try { //准备源结构信息 #region 准备源结构信息 //如果当前结构的加载方式是连接,则需要补全结构明细信息 List <SchemaInfoTuple> sourceSchemaInfos = this._schemaInfoTable.Values.ToList(); switch (this.CurrentSchemaLoadType) { case SchemaLoadType.Connection: { var requriedResult = SchemaAssistor.IsRequiredCompleteSchema(sourceSchemaInfos); if (requriedResult.requried) { var dialogResult = MessageBox.Show(this, "系统需要补全源结构信息以用于比较,是否继续?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (dialogResult != DialogResult.Yes) { return; } foreach (var schema in requriedResult.requiredSchemas) { await this.CompleteSchema(schema); } } } break; case SchemaLoadType.SchemaFile: { } break; } #endregion //准备目标结构信息 #region 准备目标结构信息 List <SchemaInfoTuple> targetSchemaInfos = null; switch (targetType) { case SchemaCompareTargetType.SchemaFile: { String targetSchemaFilePath = null; var selectResult = this._ofdLoadSchema.ShowDialog(); if (selectResult != DialogResult.OK) { return; } targetSchemaFilePath = this._ofdLoadSchema.FileName; try { this.ShowTipInformation("正在从文件中获取目标结构的信息..."); targetSchemaInfos = await this.LoadSchemaFromFile(targetSchemaFilePath); if (targetSchemaInfos == null || targetSchemaInfos.Count == 0) { String message = "操作已停止,目标结构无有效信息!"; this.ShowTipInformation(); MessageBox.Show(this, message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } //开始比较 SchemaCompareForm compareForm = new SchemaCompareForm(sourceSchemaInfos, targetSchemaInfos); // String fileName = Path.GetFileName(targetSchemaFilePath); compareForm.Text = $"与文件 [{targetSchemaFilePath}] 中的结构信息比较"; compareForm.Show(this); } catch (Exception exc) { String message = "操作已终止,目标结构加载失败!"; this.ShowErrorInformation(message); MessageBox.Show(this, message + exc.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); } } break; case SchemaCompareTargetType.Connection: { ConnectionSchemaForm schemaForm = new ConnectionSchemaForm(); schemaForm.ShowDialog(this); if (!schemaForm.CanContinue) { this.ShowTipInformation("比较操作已取消!"); return; } targetSchemaInfos = schemaForm.SchemaInfoTuples; SchemaCompareForm compareForm = new SchemaCompareForm(sourceSchemaInfos, targetSchemaInfos); // String fileName = Path.GetFileName(targetSchemaFilePath); compareForm.Text = $"与从数据连接 [{ schemaForm.ConnectionString}] 获取的结构信息比较"; compareForm.Show(this); } break; } #endregion this.ShowTipInformation(); } finally { this.EnableContol(true); this.LeaveBusyingState(); } }
/// <summary> /// 比较两个结构信息集合,并返回之间的差异(包含相同的信息项) /// </summary> /// <remarks>两个集合中的信息的 <see cref="SchemaInfoTuple.SchemaType"/> 值需要相同 </remarks> /// <param name="sourceSchemas"></param> /// <param name="targetSchemas"></param> /// <returns></returns> public static List <SchemaDifferenceInfo> CompareSchemaInfo(IEnumerable <SchemaInfoTuple> sourceSchemas, IEnumerable <SchemaInfoTuple> targetSchemas) { List <SchemaDifferenceInfo> differenceInfos = new List <SchemaDifferenceInfo>(); //层1:表、视图、函数、存储过程 //层2:列、索引 //比较层1 var sourceTopSchemas = sourceSchemas.Select(t => t.ObjectSchema).ToList(); var targetTopSchemas = targetSchemas.Select(t => t.ObjectSchema).ToList(); var topSchemaDifferenceInfos = CompareObjectSchemas(sourceTopSchemas, targetTopSchemas, out var topChangeFlag); var topSchemaDifferenceTypeTable = topSchemaDifferenceInfos.ToDictionary(t => t.Schema); differenceInfos.AddRange(topSchemaDifferenceInfos); Dictionary <String, SchemaInfoTuple> targetSchemaInfoTable = new Dictionary <String, SchemaInfoTuple>(); foreach (var schema in targetSchemas) { targetSchemaInfoTable.Add(schema.ObjectSchema.Name, schema); } //比较层2 foreach (var sourceSchema in sourceSchemas) { SchemaInfoTuple targetSchema = null; if (targetSchemaInfoTable.ContainsKey(sourceSchema.ObjectSchema.Name)) { targetSchema = targetSchemaInfoTable[sourceSchema.ObjectSchema.Name]; } switch (sourceSchema.SchemaType) { case SchemaType.Table: { //比较列 var columnDifferenceInfos = SchemaAssistor.CompareObjectSchemas( sourceSchema.ColumnSchemas.Cast <IObjectSchema>(), targetSchema?.ColumnSchemas.Cast <IObjectSchema>(), out var changeFlag); differenceInfos.AddRange(columnDifferenceInfos); //将变化中删除的列添加至目标结构中 var deletedColumnSchemas = columnDifferenceInfos.Where(t => t.DifferenceType == SchemaDifferenceType.Delete).Select(t => t.Schema).Cast <ColumnSchemaExtend>(); targetSchema?.ColumnSchemas.AddRange(deletedColumnSchemas); //如果第二层的信息发生了变化,则信息所属的父结点也应该被标记为变化 //改变可能是删除、新增、修改。当改变是新增与修改时,表中一定会存在 if (changeFlag) { if (topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType != SchemaDifferenceType.Delete) { topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType = SchemaDifferenceType.Modify; } } //比较索引 var indexDifferenceInfos = SchemaAssistor.CompareObjectSchemas( sourceSchema.IndexColumnSchemas.Cast <IObjectSchema>(), targetSchema?.IndexColumnSchemas.Cast <IObjectSchema>(), out changeFlag); differenceInfos.AddRange(indexDifferenceInfos); //将变化中删除的索引添加至目标结构中 var deletedIndexColumnSchemas = indexDifferenceInfos.Where(t => t.DifferenceType == SchemaDifferenceType.Delete).Select(t => t.Schema).Cast <IndexSchema>(); targetSchema?.IndexColumnSchemas.AddRange(deletedIndexColumnSchemas); //如果第二层的信息发生了变化 if (changeFlag) { if (topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType != SchemaDifferenceType.Delete) { topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType = SchemaDifferenceType.Modify; } } } break; case SchemaType.View: { //比较列 var columnDifferenceInfos = SchemaAssistor.CompareObjectSchemas( sourceSchema.ColumnSchemas.Cast <IObjectSchema>(), targetSchema?.ColumnSchemas.Cast <IObjectSchema>(), out var changeFlag); differenceInfos.AddRange(columnDifferenceInfos); //将变化中删除的列添加至目标结构中 var deletedIndexColumnSchemas = columnDifferenceInfos.Where(t => t.DifferenceType == SchemaDifferenceType.Delete).Select(t => t.Schema).Cast <ColumnSchemaExtend>(); targetSchema?.ColumnSchemas.AddRange(deletedIndexColumnSchemas); //如果第二层的信息发生了变化 if (changeFlag) { if (topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType != SchemaDifferenceType.Delete) { topSchemaDifferenceTypeTable[targetSchema.ObjectSchema].DifferenceType = SchemaDifferenceType.Modify; } } } break; case SchemaType.Procedure: { } break; case SchemaType.Function: { } break; } } //获取新增的结构信息,上面的遍历是以源结构为集合的,所以目标结构新增的信息是遍历不到的 var addSchemaInfos = topSchemaDifferenceInfos.Where(t => t.DifferenceType == SchemaDifferenceType.Add); foreach (var addSchema in addSchemaInfos) { var targetSchema = targetSchemaInfoTable[addSchema.Schema.Name]; switch (targetSchema.SchemaType) { case SchemaType.Table: { //新增列 var columnDifferenceInfos = SchemaAssistor.CompareObjectSchemas( null, targetSchema?.ColumnSchemas.Cast <IObjectSchema>(), out var changeFlag); differenceInfos.AddRange(columnDifferenceInfos); //新增索引 var indexDifferenceInfos = SchemaAssistor.CompareObjectSchemas( null, targetSchema?.IndexColumnSchemas.Cast <IObjectSchema>(), out changeFlag); differenceInfos.AddRange(indexDifferenceInfos); } break; case SchemaType.View: { //新增列 var columnDifferenceInfos = SchemaAssistor.CompareObjectSchemas( null, targetSchema?.ColumnSchemas.Cast <IObjectSchema>(), out var changeFlag); differenceInfos.AddRange(columnDifferenceInfos); } break; case SchemaType.Procedure: { // } break; case SchemaType.Function: { // } break; } } return(differenceInfos); }
/// <summary> /// 比较两个集合的结构信息,并指示两个集合中结构信息整体上是否有差异 /// </summary> /// <param name="sourceSchemas"></param> /// <param name="targetSchemas"></param> /// <param name="changeFlag">结构信息整体上是否有差异</param> /// <returns></returns> private static List <SchemaDifferenceInfo> CompareObjectSchemas(IEnumerable <IObjectSchema> sourceSchemas, IEnumerable <IObjectSchema> targetSchemas, out Boolean changeFlag) { List <SchemaDifferenceInfo> differenceInfos = new List <SchemaDifferenceInfo>(); changeFlag = false; sourceSchemas = sourceSchemas ?? new List <IObjectSchema>(); targetSchemas = targetSchemas ?? new List <IObjectSchema>(); Dictionary <String, IObjectSchema> targetSchemaInfoTable = new Dictionary <String, IObjectSchema>(); foreach (var schema in targetSchemas) { targetSchemaInfoTable.Add(schema.Name, schema); } foreach (var sourceSchema in sourceSchemas) { //此结构在比较目标中不存在,则标记为删除 if (!targetSchemaInfoTable.ContainsKey(sourceSchema.Name)) { SchemaDifferenceInfo deletedInfo = new SchemaDifferenceInfo { Schema = sourceSchema, DifferenceType = SchemaDifferenceType.Delete }; changeFlag = true; differenceInfos.Add(deletedInfo); continue; } //如果存在 else { var targetSchema = targetSchemaInfoTable[sourceSchema.Name]; Type type = sourceSchema.GetType(); SchemaDifferenceInfo differenceInfo = new SchemaDifferenceInfo(); differenceInfo.Schema = targetSchema; differenceInfo.DifferenceType = SchemaDifferenceType.None; var equalizer = SchemaAssistor.GetSchemaEqualizer(type); //若不相等则就是修改的 if (!equalizer.Equal(sourceSchema, targetSchema)) { changeFlag = true; differenceInfo.DifferenceType = SchemaDifferenceType.Modify; } differenceInfos.Add(differenceInfo); targetSchemaInfoTable.Remove(targetSchema.Name); } } //剩余的都是新增的 foreach (var schemaItem in targetSchemaInfoTable) { SchemaDifferenceInfo addInfo = new SchemaDifferenceInfo(); addInfo.DifferenceType = SchemaDifferenceType.Add; addInfo.Schema = schemaItem.Value; differenceInfos.Add(addInfo); changeFlag = true; } return(differenceInfos); }