/// <summary> /// Check the compatibility of the given metadata with the given entity and return /// a list of errors. /// </summary> /// <param name="entity">entity</param> /// <param name="md">metadata</param> /// <param name="breakOnError">true to stop on first error</param> /// <returns>list of errors</returns> private List <string> CheckCompatibility(Entity entity, DB.Metadata md, bool breakOnError = false) { List <string> errorDetails = new List <string>(); List <Property> propertyList = new List <Property>(entity.Properties); foreach (DB.Column column in md.Columns) { Property property = propertyList.FirstOrDefault(x => x.Name == column.Name); if (property == null) { errorDetails.Add(String.Format("Additional column: {0} {1}", column.SysType, column.Name)); if (breakOnError) { break; } } else if (property.TypeName != column.SysType) { // wrong type errorDetails.Add(String.Format("Column '{0}' is of type '{1}' instead of '{2}'.", column.Name, column.SysType, property.TypeName)); propertyList.Remove(property); if (breakOnError) { break; } } else { // everything ok propertyList.Remove(property); } } // all properties still in this list are missing foreach (Property property in propertyList) { errorDetails.Add(String.Format("Missing column: {0} {1}", property.TypeName, property.Name)); if (breakOnError) { break; } } return(errorDetails); }
/// <summary> /// Refresh the given query. If the query is a 'reader' query, the entity is updated with /// the columns of the query and alls other 'reader' queries are checked for compatibility. /// </summary> /// <param name="query">the query to refresh</param> /// <param name="entity">the entity</param> /// <param name="refreshAll">if true, all reader queries are refreshed, even if the entity columns have not changed</param> /// <param name="suppressErrorMsg">if true, no MsgBox is displayed if queries are incompatible</param> private void RefreshQuery(Query query, Entity entity, bool refreshAll = false, bool suppressErrorMsg = false) { bool columnsChanged = false; try { DB.Analyzer analyzer = new DB.Analyzer(dataModel.GetConnectionString()); DB.Metadata md = analyzer.GetQueryMetadata(query.CommandText, query.CommandType); if (query.ExecuteMethod == ExecuteMethod.Reader) { columnsChanged = entity.SetColumns(md); } query.Parameters.Clear(); query.Parameters.AddRange(md.Parameters); ShowQueryOkFeedback(query); } catch (Exception ex) { query.ShowError = true; Refresh(); MessageBox.Show(this, "An error occured while refreshing the query '" + query.Name + "':\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } // if entity columns have been changed, check all other 'reader' queries if (columnsChanged || refreshAll) { List <string> erroneousQueries = new List <string>(); foreach (Query otherQuery in entity.Queries) { if (otherQuery != query && otherQuery.ExecuteMethod == ExecuteMethod.Reader) { try { DB.Analyzer analyzer = new DB.Analyzer(dataModel.GetConnectionString()); DB.Metadata md = analyzer.GetQueryMetadata(otherQuery.CommandText, otherQuery.CommandType); if (CheckCompatibility(entity, md, true).Count > 0) { if (!otherQuery.ShowError) { otherQuery.ShowError = true; erroneousQueries.Add(otherQuery.Name); } } else { ShowQueryOkFeedback(otherQuery); } } catch (Exception ex) { otherQuery.ShowError = true; Refresh(); MessageBox.Show(this, "An error occured while refreshing the query '" + otherQuery.Name + "':\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } Refresh(); if (!suppressErrorMsg) { if (erroneousQueries.Count == 1) { MessageBox.Show( this, "The result returned by the query '" + erroneousQueries[0] + "' is not compatible with the entity '" + entity.Name + "'.", "Incompatible query", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if (erroneousQueries.Count > 1) { MessageBox.Show( this, "The result returned by the following queries is not compatible with the entity '" + entity.Name + "':\r\n - " + String.Join("\r\n - ", erroneousQueries), "Incompatible queries", MessageBoxButtons.OK, MessageBoxIcon.Error); } } } else { Refresh(); } }
/// <summary> /// Show the dialog for adding a new query to an entity. /// </summary> /// <param name="entity">the entity to which a query should be added</param> private void AddNewQuery(Entity entity) { string connectionString = dataModel.GetConnectionString(); if (String.IsNullOrEmpty(connectionString)) { using (Connection frm = new Connection(connectionStringService)) { if (frm.ShowDialog(this) == DialogResult.OK) { connectionString = frm.ConnectionString; dataModel.EditorProperties.ConnectionString = frm.ConnectionStringName; } } } if (!String.IsNullOrEmpty(connectionString)) { using (AddQuery addQuery = new AddQuery(connectionString, entity.Queries)) { addQuery.Width = dataModel.DialogWidth; addQuery.Height = dataModel.DialogHeight; addQuery.Text = "Add a new query to entity \"" + entity.Name + "\""; if (addQuery.ShowDialog(this) == DialogResult.OK) { try { // get query metadata from DB DB.Analyzer analyzer = new DB.Analyzer(dataModel.GetConnectionString()); DB.Metadata md = analyzer.GetQueryMetadata(addQuery.CommandText, addQuery.CommandType); bool addOk = true; bool incompatibility = false; if (addQuery.ExecuteMethod == ExecuteMethod.Reader) { if (entity.Properties.Count == 0) { entity.SetColumns(md); } else { List <string> errorDetails = CheckCompatibility(entity, md); if (errorDetails.Count > 0) { using (CompatibilityError errorDlg = new CompatibilityError(errorDetails, addQuery.QueryName)) { if (errorDlg.ShowDialog(this) == DialogResult.OK) { entity.SetColumns(md); incompatibility = true; } else { addOk = false; } } } } } if (addOk) { Query query = new Query(this, entity) { Name = addQuery.QueryName, CommandText = addQuery.CommandText, CommandType = addQuery.CommandType, ExecuteMethod = addQuery.ExecuteMethod, ReturnType = "object" }; query.Parameters.AddRange(md.Parameters); entity.Queries.Add(query); if (incompatibility) { RefreshQuery(query, entity, true, true); okQueryTimer.Start(); } } OnModifiedWithRefresh(); } catch (Exception ex) { MessageBox.Show(this, "An error occured while adding the new query:\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); Query query = new Query(this, entity) { Name = addQuery.QueryName, CommandText = addQuery.CommandText, CommandType = addQuery.CommandType, ExecuteMethod = addQuery.ExecuteMethod, ReturnType = "object", ShowError = true }; entity.Queries.Add(query); OnModifiedWithRefresh(); } } dataModel.DialogWidth = addQuery.Width; dataModel.DialogHeight = addQuery.Height; } } }