protected virtual void OnErrorRaised(RecoverableErrorEventArgs e) { if (ErrorRaised != null) { ErrorRaised(this, e); } }
public static void HandleEvent(RecoverableErrorEventArgs args, IAsyncConnection conn) { using (var dialog = new ErrorWindow()) { dialog._conn = conn; dialog.txtMessage.Text = args.Message ?? args.Exception.Message; dialog.txtErrorDetails.Text = Utils.IndentXml(args.Exception.ToAml()); dialog.txtQuery.Text = Utils.IndentXml(args.Exception.Query); dialog.TopMost = true; switch (dialog.ShowDialog()) { case DialogResult.Ignore: args.RecoveryOption = RecoveryOption.Skip; break; case DialogResult.Retry: args.RecoveryOption = RecoveryOption.Retry; var doc = new XmlDocument(); doc.LoadXml(dialog.txtQuery.Text); args.NewQuery = doc.DocumentElement; break; default: args.RecoveryOption = RecoveryOption.Abort; break; } } }
public static void HandleEvent(RecoverableErrorEventArgs args) { using (var dialog = new ErrorWindow()) { dialog.txtMessage.Text = args.Message ?? args.Exception.Message; dialog.txtErrorDetails.Text = Utils.IndentXml(args.Exception.AsAmlString()); dialog.txtQuery.Text = Utils.IndentXml(args.Exception.Query); dialog.TopMost = true; switch (dialog.ShowDialog()) { case DialogResult.Ignore: args.RecoveryOption = RecoveryOption.Skip; break; case DialogResult.Retry: args.RecoveryOption = RecoveryOption.Retry; var doc = new XmlDocument(); doc.LoadXml(dialog.txtQuery.Text); args.NewQuery = doc.DocumentElement; break; default: args.RecoveryOption = RecoveryOption.Abort; break; } } }
private void HandleErrorDefault(RecoverableErrorEventArgs args, XmlNode query) { _logger?.LogError(args.Exception, null); var isAuto = false; if (args.Exception.FaultCode == "0" && (query.Attribute("action") == "delete" || query.Attribute("action") == "purge")) { args.RecoveryOption = RecoveryOption.Skip; isAuto = true; } else if (args.Exception.Message.Trim() == "Identity already exists." && query.Attribute("type") == "Identity" && query.Attribute("action") == "add") { ((XmlElement)query).SetAttribute("action", "edit"); args.NewQuery = query; args.RecoveryOption = RecoveryOption.Retry; isAuto = true; } //else if (args.Exception.FaultCode == "SOAP-ENV:Server.PropertiesAreNotUniqueException") //{ // args.Exception.Fault.Element("detail").Element("af:item"); //} if (isAuto) { _logger?.LogInformation("Automatically decided to {action}", args.RecoveryOption.ToString()); } else { OnErrorRaised(args); _logger?.LogInformation("User decided to {action}", args.RecoveryOption.ToString()); } }
private void InstallLines() { string upgradeId = Guid.NewGuid().ToString("N").ToUpperInvariant(); ExportProcessor.EnsureSystemData(_conn, ref _itemTypes); try { bool cont; RecoverableErrorEventArgs args; XmlNode query; XmlElement newQuery; ItemType itemType; string configId; ReportProgress(0, "Starting install."); _conn.Apply(@"<Item type='DatabaseUpgrade' action='merge' id='@0'> <upgrade_status>0</upgrade_status> <is_latest>0</is_latest> <type>1</type> <os_user>@1</os_user> <name>@2</name> <description>@3</description> <applied_on>__now()</applied_on> </Item>" , upgradeId , Environment.UserDomainName + "\\" + Environment.UserName , _script.Title.Left(64) , _script.Description.Left(512)).AssertNoError(); IEnumerable<IReadOnlyItem> items; foreach (var line in _lines.Skip(_currLine).ToList()) { cont = true; ReportProgress((int)(_currLine * 80.0 / _lines.Count), string.Format("Performing {0} ({1} of {2})", line.ToString(), _currLine + 1, _lines.Count)); query = line.Script; while (cont) { try { // If the original item uses a where clause or is versionable or the target item is versionable if ((query.Attribute("action") == "merge" || query.Attribute("action") == "edit") && TryGetConfigId(query, out configId) && (query.Attribute("where") != null || (_itemTypes.TryGetValue(query.Attribute("type").ToLowerInvariant(), out itemType)) && itemType.IsVersionable )) { newQuery = query.Clone() as XmlElement; newQuery.InnerXml = ""; newQuery.SetAttribute("action", "get"); newQuery.SetAttribute("select", "id"); // The item type became versionable in the target database if (newQuery.Attribute("where") == null) { newQuery.RemoveAttribute("id"); newQuery.SetAttribute("where", string.Format("[{0}].[config_id] = '{1}'", query.Attribute("type", "").Replace(' ', '_'), configId)); } // If the item exists, get the id for use in the relationships // If the item doesn't exist, make sure the id = config_id for the add items = _conn.Apply(newQuery).Items(); string sourceId = items.Any() ? items.First().Attribute("id").Value : configId; newQuery = query.Clone() as XmlElement; newQuery.SetAttribute("id", sourceId); newQuery.RemoveAttribute("where"); newQuery.RemoveAttribute(XmlFlags.Attr_ConfigId); query = newQuery; string relatedId; string whereClause; // Check relationships and match based on source_id and related_id where necessary foreach (var rel in query.ElementsByXPath("Relationships/Item[related_id]").ToList()) { if (rel.Element("related_id").Element("Item") == null) { relatedId = rel.InnerText; } else { relatedId = rel.Element("related_id").Element("Item").Attribute("id"); } whereClause = string.Format("[{0}].[source_id]='{1}' and [{0}].[related_id]='{2}'" , rel.Attribute("type", "").Replace(' ', '_'), sourceId, relatedId); if (!string.IsNullOrEmpty(relatedId)) { newQuery = rel.OwnerDocument.CreateElement("Item"); newQuery.SetAttribute("type", rel.Attribute("type")); newQuery.SetAttribute("where", whereClause); newQuery.SetAttribute("action", "get"); items = _conn.Apply(newQuery).Items(); if (items.Any()) { rel.RemoveAttribute("id"); rel.SetAttribute("where", whereClause); rel.SetAttribute("action", "edit"); } } } } items = _conn.Apply(query).AssertItems(); if (line.Type == InstallType.Create) line.InstalledId = items.First().Attribute("id").Value; // Execute any sql scripts var sqlScripts = line.Script .DescendantsAndSelf(e => e.Attribute(XmlFlags.Attr_SqlScript, "") != "") .Select(e => e.Attribute(XmlFlags.Attr_SqlScript, "")); if (sqlScripts.Any()) { _conn.ApplySql(sqlScripts.Aggregate((p, c) => p + Environment.NewLine + c)).AssertNoError(); } cont = false; } catch (ServerException ex) { _log.Append(DateTime.Now.ToString("s")).AppendLine(": ERROR"); _log.AppendLine(ex.AsAmlString()); _log.AppendLine(" for query "); _log.AppendLine(ex.Query); args = new RecoverableErrorEventArgs() { Exception = ex }; if (line.Type == InstallType.DependencyCheck && ex.FaultCode == "0") { args.Message = "Unable to find required dependency " + line.Reference.Type + ": " + line.Reference.KeyedName; } OnErrorRaised(args); switch (args.RecoveryOption) { case RecoveryOption.Abort: _log.Append(DateTime.Now.ToString("s")).AppendLine(": Install aborted."); throw; case RecoveryOption.Retry: query = args.NewQuery ?? query; _log.Append(DateTime.Now.ToString("s")).AppendLine(": Retrying install step with query:"); _log.AppendLine(query.OuterXml); break; case RecoveryOption.Skip: _log.Append(DateTime.Now.ToString("s")).AppendLine(": Skipping install step."); cont = false; break; } } } _currLine++; } if (_script.AddPackage) { var pkg = new DatabasePackage(_conn); pkg.Write(_script, e => { args = new RecoverableErrorEventArgs() { Message = e }; OnErrorRaised(args); switch (args.RecoveryOption) { case RecoveryOption.Skip: return DatabasePackageAction.RemoveElementsFromPackages; case RecoveryOption.Retry: return DatabasePackageAction.TryAgain; default: return DatabasePackageAction.Abort; } }, (i, m) => { ReportProgress((int)(i * 0.2 + 80), m); }); } _conn.Apply("<Item type=\"DatabaseUpgrade\" action=\"merge\" id=\"@0\"><upgrade_status>1</upgrade_status></Item>", upgradeId).AssertNoError(); OnActionComplete(new ActionCompleteEventArgs()); } catch (Exception ex) { _conn.Apply("<Item type=\"DatabaseUpgrade\" action=\"merge\" id=\"@0\"><upgrade_status>2</upgrade_status></Item>", upgradeId); //.AssertNoError(); OnActionComplete(new ActionCompleteEventArgs() { Exception = ex }); } }
protected virtual void OnErrorRaised(RecoverableErrorEventArgs e) { if (ErrorRaised != null) ErrorRaised(this, e); }
private void InstallLines() { string upgradeId = Guid.NewGuid().ToString("N").ToUpperInvariant(); ExportProcessor.EnsureSystemData(_conn, ref _itemTypes); try { bool cont; RecoverableErrorEventArgs args; XmlNode query; XmlElement newQuery; ItemType itemType; string configId; ReportProgress(0, "Starting install."); _conn.Apply(@"<Item type='DatabaseUpgrade' action='merge' id='@0'> <upgrade_status>0</upgrade_status> <is_latest>0</is_latest> <type>1</type> <os_user>@1</os_user> <name>@2</name> <description>@3</description> <applied_on>__now()</applied_on> </Item>" , upgradeId , Environment.UserDomainName + "\\" + Environment.UserName , _script.Title.Left(64) , _script.Description.Left(512)).AssertNoError(); IEnumerable <IReadOnlyItem> items; foreach (var line in _lines.Skip(_currLine).ToList()) { cont = true; ReportProgress((int)(_currLine * 80.0 / _lines.Count), string.Format("Performing {0} ({1} of {2})", line.ToString(), _currLine + 1, _lines.Count)); query = line.Script; while (cont) { try { // If the original item uses a where clause or is versionable or the target item is versionable if ((query.Attribute("action") == "merge" || query.Attribute("action") == "edit") && TryGetConfigId(query, out configId) && (query.Attribute("where") != null || (_itemTypes.TryGetValue(query.Attribute("type").ToLowerInvariant(), out itemType)) && itemType.IsVersionable)) { newQuery = query.Clone() as XmlElement; newQuery.InnerXml = ""; newQuery.SetAttribute("action", "get"); newQuery.SetAttribute("select", "id"); // The item type became versionable in the target database if (newQuery.Attribute("where") == null) { newQuery.RemoveAttribute("id"); newQuery.SetAttribute("where", string.Format("[{0}].[config_id] = '{1}'", query.Attribute("type", "").Replace(' ', '_'), configId)); } // If the item exists, get the id for use in the relationships // If the item doesn't exist, make sure the id = config_id for the add items = _conn.Apply(newQuery.OuterXml).Items(); string sourceId = items.Any() ? items.First().Attribute("id").Value : configId; newQuery = query.Clone() as XmlElement; newQuery.SetAttribute("id", sourceId); newQuery.RemoveAttribute("where"); newQuery.RemoveAttribute(XmlFlags.Attr_ConfigId); query = newQuery; string relatedId; string whereClause; // Check relationships and match based on source_id and related_id where necessary var rels = query.ElementsByXPath("Relationships/Item[related_id]").ToArray(); foreach (var rel in rels) { if (rel.Element("related_id").Element("Item") == null) { relatedId = rel.InnerText; } else { relatedId = rel.Element("related_id").Element("Item").Attribute("id"); } whereClause = string.Format("[{0}].[source_id]='{1}' and [{0}].[related_id]='{2}'" , rel.Attribute("type", "").Replace(' ', '_'), sourceId, relatedId); if (!string.IsNullOrEmpty(relatedId)) { newQuery = rel.OwnerDocument.CreateElement("Item"); newQuery.SetAttribute("type", rel.Attribute("type")); newQuery.SetAttribute("where", whereClause); newQuery.SetAttribute("action", "get"); items = _conn.Apply(newQuery.OuterXml).Items(); rel.RemoveAttribute("id"); if (items.Any()) { rel.SetAttribute("where", whereClause); rel.SetAttribute("action", "edit"); } else { rel.SetAttribute("action", "add"); } } } } //Fix Relationships on cmf generated ItemTypes if ((query.Attribute("action") == "merge" || query.Attribute("action") == "edit") && query.Attribute("_cmf_generated") != null && query.Attribute("where") != null) { var sourceItem = _conn.Apply($"<Item action='get' type='ItemType'><name>{query.Element("name").InnerText}</name></Item>").AssertItem(); var sourceId = sourceItem.Id(); var queryClone = query.Clone() as XmlElement; queryClone.SetAttribute("id", sourceId); queryClone.RemoveAttribute("where"); query = queryClone; string relatedId = ""; string whereClause; foreach (var rel in query.ElementsByXPath("Relationships/Item[related_id]").ToList()) { if (rel.Element("related_id").Element("Item") == null) { relatedId = rel.Element("related_id").InnerText; } else { var relatedQuery = rel.Element("related_id").Element("Item"); relatedQuery.Attr("action", "get"); relatedId = _conn.Apply(relatedQuery).AssertItem().Id(); rel.Element("related_id").InnerText = relatedId; } whereClause = string.Format("[{0}].[source_id]='{1}' and [{0}].[related_id]='{2}'" , rel.Attribute("type", "").Replace(' ', '_'), sourceId, relatedId); if (!string.IsNullOrEmpty(relatedId)) { rel.RemoveAttribute("id"); rel.SetAttribute("where", whereClause); rel.SetAttribute("action", "merge"); } } } var cmd = new Command(query.OuterXml); cmd.Settings = x => x.Timeout = TimeSpan.FromMinutes(5); items = _conn.Apply(cmd).AssertItems(); if (line.Type == InstallType.Create) { line.InstalledId = items.First().Attribute("id").Value; } // Execute any sql scripts var sqlScripts = line.Script .DescendantsAndSelf(e => e.Attribute(XmlFlags.Attr_SqlScript, "") != "") .Select(e => e.Attribute(XmlFlags.Attr_SqlScript, "")); if (sqlScripts.Any()) { _conn.ApplySql(sqlScripts.Aggregate((p, c) => p + Environment.NewLine + c)).AssertNoError(); } cont = false; } catch (ServerException ex) { _log.Append(DateTime.Now.ToString("s")).AppendLine(": ERROR"); _log.AppendLine(ex.ToAml()); _log.AppendLine(" for query "); _log.AppendLine(ex.Query); if (ex.Message.Trim() == "No items of type ? found." && (query.Attribute("action") == "delete" || query.Attribute("action") == "purge")) { // Ignore errors with trying to delete something that isn't there. _log.Append(DateTime.Now.ToString("s")).AppendLine(": Skipping install step"); cont = false; break; } else { args = new RecoverableErrorEventArgs() { Exception = ex }; if (line.Type == InstallType.DependencyCheck && ex.FaultCode == "0") { args.Message = "Unable to find required dependency " + line.Reference.Type + ": " + line.Reference.KeyedName; } OnErrorRaised(args); switch (args.RecoveryOption) { case RecoveryOption.Abort: _log.Append(DateTime.Now.ToString("s")).AppendLine(": Install aborted."); throw; case RecoveryOption.Retry: query = args.NewQuery ?? query; _log.Append(DateTime.Now.ToString("s")).AppendLine(": Retrying install step with query:"); _log.AppendLine(query.OuterXml); break; case RecoveryOption.Skip: _log.Append(DateTime.Now.ToString("s")).AppendLine(": Skipping install step."); cont = false; break; } } } } _currLine++; } if (_script.AddPackage) { var pkg = new DatabasePackage(_conn); pkg.Write(_script, e => { args = new RecoverableErrorEventArgs() { Message = e }; OnErrorRaised(args); switch (args.RecoveryOption) { case RecoveryOption.Skip: return(DatabasePackageAction.RemoveElementsFromPackages); case RecoveryOption.Retry: return(DatabasePackageAction.TryAgain); default: return(DatabasePackageAction.Abort); } }, (i, m) => { ReportProgress((int)(i * 0.2 + 80), m); }); } _conn.Apply("<Item type=\"DatabaseUpgrade\" action=\"merge\" id=\"@0\"><upgrade_status>1</upgrade_status></Item>", upgradeId).AssertNoError(); OnActionComplete(new ActionCompleteEventArgs()); } catch (Exception ex) { _conn.Apply("<Item type=\"DatabaseUpgrade\" action=\"merge\" id=\"@0\"><upgrade_status>2</upgrade_status></Item>", upgradeId); //.AssertNoError(); OnActionComplete(new ActionCompleteEventArgs() { Exception = ex }); } }
private void InstallLines() { ExportProcessor.EnsureSystemData(_conn, ref _itemTypes); bool repeat; RecoverableErrorEventArgs args; XmlNode query; XmlElement newQuery; ItemType itemType; string configId; ReportProgress(0, "Starting install."); IEnumerable <IReadOnlyItem> items; foreach (var line in _lines.Skip(_currLine).ToList()) { repeat = true; ReportProgress((int)(_currLine * 80.0 / _lines.Count), string.Format("Performing {0} ({1} of {2})", line.ToString(), _currLine + 1, _lines.Count)); query = line.Script; while (repeat) { try { // If the original item uses a where clause or is versionable or the target item is versionable if ((query.Attribute("action") == "merge" || query.Attribute("action") == "edit") && TryGetConfigId(query, out configId) && (query.Attribute("where") != null || (_itemTypes.TryGetValue(query.Attribute("type").ToLowerInvariant(), out itemType)) && itemType.IsVersionable)) { newQuery = query.Clone() as XmlElement; newQuery.InnerXml = ""; newQuery.SetAttribute("action", "get"); newQuery.SetAttribute("select", "id"); // The item type became versionable in the target database if (newQuery.Attribute("where") == null) { newQuery.RemoveAttribute("id"); newQuery.SetAttribute("where", string.Format("[{0}].[config_id] = '{1}'", query.Attribute("type", "").Replace(' ', '_'), configId)); } // If the item exists, get the id for use in the relationships // If the item doesn't exist, make sure the id = config_id for the add items = _conn.Apply(newQuery.OuterXml).Items(); string sourceId = items.Any() ? items.First().Attribute("id").Value : configId; newQuery = query.Clone() as XmlElement; newQuery.SetAttribute("id", sourceId); newQuery.RemoveAttribute("where"); newQuery.RemoveAttribute(XmlFlags.Attr_ConfigId); query = newQuery; string relatedId; string whereClause; // Check relationships and match based on source_id and related_id where necessary var rels = query.ElementsByXPath("Relationships/Item[related_id]").ToArray(); foreach (var rel in rels) { if (rel.Element("related_id").Element("Item") == null) { relatedId = rel.InnerText; } else if (rel.Element("related_id").Element("Item").Attribute("action") == "get") { var relatedQuery = rel.Element("related_id").Element("Item"); relatedId = _conn.Apply(relatedQuery).AssertItem().Id(); } else { relatedId = rel.Element("related_id").Element("Item").Attribute("id"); } whereClause = string.Format("[{0}].[source_id]='{1}' and [{0}].[related_id]='{2}'" , rel.Attribute("type", "").Replace(' ', '_'), sourceId, relatedId); if (!string.IsNullOrEmpty(relatedId)) { newQuery = rel.OwnerDocument.CreateElement("Item"); newQuery.SetAttribute("type", rel.Attribute("type")); newQuery.SetAttribute("where", whereClause); newQuery.SetAttribute("action", "get"); items = _conn.Apply(newQuery.OuterXml).Items(); rel.RemoveAttribute("id"); if (items.Any()) { rel.SetAttribute("where", whereClause); rel.SetAttribute("action", "edit"); } else { rel.SetAttribute("action", "add"); } } } } //Fix Relationships on cmf generated ItemTypes if ((query.Attribute("action") == "merge" || query.Attribute("action") == "edit") && query.Attribute("_cmf_generated") != null && query.Attribute("where") != null) { var sourceItem = _conn.Apply($"<Item action='get' type='ItemType'><name>{query.Element("name").InnerText}</name></Item>").AssertItem(); var sourceId = sourceItem.Id(); var queryClone = query.Clone() as XmlElement; queryClone.SetAttribute("id", sourceId); queryClone.RemoveAttribute("where"); query = queryClone; string relatedId = ""; string whereClause; foreach (var rel in query.ElementsByXPath("Relationships/Item[related_id]").ToList()) { if (rel.Element("related_id").Element("Item") == null) { relatedId = rel.Element("related_id").InnerText; } else { var relatedQuery = rel.Element("related_id").Element("Item"); relatedQuery.Attr("action", "get"); relatedId = _conn.Apply(relatedQuery).AssertItem().Id(); rel.Element("related_id").InnerText = relatedId; } whereClause = string.Format("[{0}].[source_id]='{1}' and [{0}].[related_id]='{2}'" , rel.Attribute("type", "").Replace(' ', '_'), sourceId, relatedId); if (!string.IsNullOrEmpty(relatedId)) { rel.RemoveAttribute("id"); rel.SetAttribute("where", whereClause); rel.SetAttribute("action", "merge"); } } } var cmd = new Command(query.OuterXml) { Settings = x => x.Timeout = TimeSpan.FromMinutes(5) }; items = _conn.Apply(cmd).AssertItems(); if (line.Type == InstallType.Create) { line.InstalledId = items.First().Attribute("id").Value; } // Execute any sql scripts var sqlScripts = line.Script .DescendantsAndSelf(e => e.Attribute(XmlFlags.Attr_SqlScript, "") != "") .Select(e => e.Attribute(XmlFlags.Attr_SqlScript, "")); if (sqlScripts.Any()) { _conn.ApplySql(sqlScripts.Aggregate((p, c) => p + Environment.NewLine + c)).AssertNoError(); } repeat = false; } catch (ServerException ex) { using (SharedUtils.StartActivity("InstallProcessor.Install.HandleServerError")) { args = new RecoverableErrorEventArgs() { Exception = ex }; if (line.Type == InstallType.DependencyCheck && ex.FaultCode == "0") { args.Message = "Unable to find required dependency " + line.Reference.Type + ": " + line.Reference.KeyedName; } HandleErrorDefault(args, query); switch (args.RecoveryOption) { case RecoveryOption.Abort: throw; case RecoveryOption.Retry: query = args.NewQuery ?? query; _logger?.LogInformation("{NewQuery}", query.OuterXml); break; default: // case RecoveryOption.Skip: repeat = false; break; } } } } _currLine++; } }