Esempio n. 1
0
        /// <summary>
        /// Performs the database scripts execution against the specified server/ database settings
        /// </summary>
        /// <param name="serverName">Name of the SQL server to target</param>
        /// <param name="overrides">List of database override settings to use in execution</param>
        /// <returns></returns>
        internal async Task <int> RunDatabaseBuild()
        {
            this.returnValue = (int)RunnerReturn.BuildResultInconclusive;

            ConnectionData   connData         = null;
            BackgroundWorker bg               = null;
            DoWorkEventArgs  e                = null;
            SqlBuildRunData  runData          = new SqlBuildRunData();
            string           targetDatabase   = overrides[0].OverrideDbTarget;
            string           loggingDirectory = Path.Combine(ThreadedExecution.WorkingDirectory, server, targetDatabase);

            try
            {
                //Start setting properties on the object that contains the run configuration data.
                runData.BuildType = "Other";
                if (!string.IsNullOrEmpty(cmdArgs.Description))
                {
                    runData.BuildDescription = cmdArgs.Description;
                }
                else
                {
                    runData.BuildDescription = "Threaded Multi-Database. Run ID:" + ThreadedExecution.RunID;
                }

                runData.IsTrial                 = this.isTrial;
                runData.RunScriptOnly           = false;
                runData.TargetDatabaseOverrides = overrides;
                runData.Server          = this.server;
                runData.IsTransactional = cmdArgs.Transactional;
                if (this.cmdArgs.LogToDatabaseName.Length > 0)
                {
                    runData.LogToDatabaseName = this.cmdArgs.LogToDatabaseName;
                }

                runData.PlatinumDacPacFileName = cmdArgs.DacPacArgs.PlatinumDacpac;
                runData.BuildRevision          = cmdArgs.BuildRevision;
                runData.DefaultScriptTimeout   = cmdArgs.DefaultScriptTimeout;
                runData.AllowObjectDelete      = cmdArgs.AllowObjectDelete;


                //Initilize the logging directory for this run
                if (!Directory.Exists(loggingDirectory))
                {
                    Directory.CreateDirectory(loggingDirectory);
                }

                if (forceCustomDacpac)
                {
                    runData.ForceCustomDacpac = true;
                    //This will set the BuildData and BuildFileName and ProjectFileName properties on runData
                    var status = DacPacHelper.UpdateBuildRunDataForDacPacSync(ref runData, server, targetDatabase, this.authType, this.username, this.password, loggingDirectory, cmdArgs.BuildRevision, cmdArgs.DefaultScriptTimeout, cmdArgs.AllowObjectDelete);
                    switch (status)
                    {
                    case DacpacDeltasStatus.Success:
                        //nothing to do
                        break;

                    case DacpacDeltasStatus.InSync:
                    case DacpacDeltasStatus.OnlyPostDeployment:
                        log.LogInformation($"Target database {targetDatabase} is already in sync with {cmdArgs.DacPacArgs.PlatinumDacpac}. Nothing to do!");
                        this.returnValue = (int)RunnerReturn.DacpacDatabasesInSync;
                        break;

                    default:
                        log.LogError($"Error creating custom dacpac and scripts for {targetDatabase}. No update was performed");
                        this.returnValue = (int)RunnerReturn.PackageCreationError;
                        return((int)RunnerReturn.PackageCreationError);;
                    }
                }
                else
                {
                    runData.ForceCustomDacpac = false;
                    //Get a full copy of the build data to work with (avoid threading sync issues)
                    SqlSyncBuildData buildData = new SqlSyncBuildData();

                    string xml = "<?xml version=\"1.0\" standalone=\"yes\"?>\r\n" + ThreadedExecution.BuildData.GetXml();
                    using (StringReader sr = new StringReader(xml))
                    {
                        buildData.ReadXml(sr);
                    }
                    //Clear out any existing ComittedScript data.. just log what is relevent to this run.
                    buildData.CommittedScript.Clear();


                    runData.BuildData       = buildData;
                    runData.ProjectFileName = Path.Combine(loggingDirectory, Path.GetFileName(ThreadedExecution.ProjectFileName));
                    runData.BuildFileName   = ThreadedExecution.BuildZipFileName;
                }



                //Create a connection object.. all we need is the server here, the DB will be filled in at execution time
                connData = new ConnectionData(server, "");
                if (this.cmdArgs.AuthenticationArgs.UserName.Length > 0 && this.cmdArgs.AuthenticationArgs.Password.Length > 0)
                {
                    connData.UserId   = cmdArgs.AuthenticationArgs.UserName;
                    connData.Password = cmdArgs.AuthenticationArgs.Password;
                }
                connData.AuthenticationType = this.cmdArgs.AuthenticationArgs.AuthenticationType;

                //Set the log file name
                string logFile = Path.Combine(loggingDirectory, "ExecutionLog.log");

                //Create the objects that will handle the event communication back.
                bg = new BackgroundWorker();
                //bg.ProgressChanged += Bg_ProgressChanged;
                bg.WorkerReportsProgress = true;
                e = new DoWorkEventArgs(null);
            }
            catch (Exception exe)
            {
                log.LogError(exe, $"Error Initializing run for {this.TargetTag}");
                WriteErrorLog(loggingDirectory, exe.ToString());
                this.returnValue = (int)ExecutionReturn.RunInitializationError;
                return((int)ExecutionReturn.RunInitializationError);;
            }

            log.LogDebug("Initializing run for " + this.TargetTag + ". Starting \"ProcessBuild\"");

            try
            {
                //Initilize the run helper object and kick it off.
                SqlBuildHelper helper = new SqlBuildHelper(connData, true, string.Empty, cmdArgs.Transactional); //don't need an "external" log for this, it's all external!
                helper.BuildCommittedEvent              += new BuildCommittedEventHandler(helper_BuildCommittedEvent);
                helper.BuildErrorRollBackEvent          += new EventHandler(helper_BuildErrorRollBackEvent);
                helper.BuildSuccessTrialRolledBackEvent += new EventHandler(helper_BuildSuccessTrialRolledBackEvent);
                await Task.Run(() =>
                {
                    helper.ProcessBuild(runData, bg, e, ThreadedExecution.BatchColl, this.buildRequestedBy, cmdArgs.TimeoutRetryCount);
                });
            }
            catch (Exception exe)
            {
                log.LogError("Error Processing run for " + this.TargetTag, exe);
                WriteErrorLog(loggingDirectory, exe.ToString());
                this.returnValue = (int)ExecutionReturn.ProcessBuildError;
                return((int)ExecutionReturn.ProcessBuildError);;
            }
            return(0);
        }