protected virtual void OnErrorRaised(RecoverableErrorEventArgs e)
 {
     if (ErrorRaised != null)
     {
         ErrorRaised(this, e);
     }
 }
Exemple #2
0
        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++;
            }
        }