Advertisement
Guest User

SQL Deployment OnExecute Method

a guest
Dec 31st, 2015
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.90 KB | None | 0 0
  1. protected override void OnExecute(DeploymentPlanContributorContext context)
  2. {
  3. // Obtain the first step in the Plan from the provided context
  4. DeploymentStep nextStep = context.PlanHandle.Head;
  5. int batchId = 0;
  6. BeginPreDeploymentScriptStep beforePreDeploy = null;
  7.  
  8. // Loop through all steps in the deployment plan
  9. while (nextStep != null)
  10. {
  11. // Increment the step pointer, saving both the current and next steps
  12. DeploymentStep currentStep = nextStep;
  13. nextStep = currentStep.Next;
  14.  
  15. #region Additional Processing Steps
  16. // Look for steps that mark the pre/post deployment scripts
  17. // These steps will always be in the deployment plan even if the
  18. // user's project does not have a pre/post deployment script
  19. if (currentStep is BeginPreDeploymentScriptStep)
  20. {
  21. // This step marks the begining of the predeployment script.
  22. // Save the step and move on.
  23. beforePreDeploy = (BeginPreDeploymentScriptStep)currentStep;
  24. continue;
  25. }
  26. if (currentStep is BeginPostDeploymentScriptStep)
  27. {
  28. // This is the step that marks the beginning of the post deployment script.
  29. // We do not continue processing after this point.
  30. break;
  31. }
  32. if (currentStep is SqlPrintStep)
  33. {
  34. // We do not need to put if statements around these
  35. continue;
  36. }
  37.  
  38. // if we have not yet found the beginning of the pre-deployment script steps,
  39. // skip to the next step.
  40. if (beforePreDeploy == null)
  41. {
  42. // We only surround the "main" statement block with conditional
  43. // statements
  44. continue;
  45. }
  46.  
  47. // Determine if this is a step that we need to surround with a conditional statement
  48. DeploymentScriptDomStep domStep = currentStep as DeploymentScriptDomStep;
  49. if (domStep == null)
  50. {
  51. // This step is not a step that we know how to modify,
  52. // so skip to the next step.
  53. continue;
  54. }
  55.  
  56. TSqlScript script = domStep.Script as TSqlScript;
  57. if (script == null)
  58. {
  59. // The script dom step does not have a script with batches - skip
  60. continue;
  61. }
  62.  
  63. // Loop through all the batches in the script for this step. All the statements
  64. // in the batch will be enclosed in an if statement that will check the
  65. // table to ensure that the batch has not already been executed
  66. TSqlObject sqlObject;
  67. string stepDescription;
  68. GetStepInfo(domStep, out stepDescription, out sqlObject);
  69. int batchCount = script.Batches.Count;
  70.  
  71. for (int batchIndex = 0; batchIndex < batchCount; batchIndex++)
  72. {
  73. #region Batch Processing
  74. // Create the if statement that will contain the batch's contents
  75. IfStatement ifBatchNotExecutedStatement = CreateIfNotExecutedStatement(batchId);
  76. BeginEndBlockStatement statementBlock = new BeginEndBlockStatement();
  77. ifBatchNotExecutedStatement.ThenStatement = statementBlock;
  78. statementBlock.StatementList = new StatementList();
  79.  
  80. TSqlBatch batch = script.Batches[batchIndex];
  81. int statementCount = batch.Statements.Count;
  82.  
  83. // Loop through all statements in the batch, embedding those in an sp_execsql
  84. // statement that must be handled this way (schemas, stored procedures,
  85. // views, functions, and triggers).
  86. for (int statementIndex = 0; statementIndex < statementCount; statementIndex++)
  87. {
  88. #region Additional Statement Processing
  89. TSqlStatement smnt = batch.Statements[statementIndex];
  90.  
  91. if (IsStatementEscaped(sqlObject))
  92. {
  93. // "escape" this statement by embedding it in a sp_executesql statement
  94. string statementScript;
  95. domStep.ScriptGenerator.GenerateScript(smnt, out statementScript);
  96. ExecuteStatement spExecuteSql = CreateExecuteSql(statementScript);
  97. smnt = spExecuteSql;
  98. }
  99.  
  100. statementBlock.StatementList.Statements.Add(smnt);
  101.  
  102. #endregion
  103. }
  104.  
  105. // Add an insert statement to track that all the statements in this
  106. // batch were executed. Turn on nocount to improve performance by
  107. // avoiding row inserted messages from the server
  108. string batchDescription = string.Format(CultureInfo.InvariantCulture,
  109. "{0} batch {1}", stepDescription, batchIndex);
  110.  
  111. PredicateSetStatement noCountOff = new PredicateSetStatement();
  112. noCountOff.IsOn = false;
  113. noCountOff.Options = SetOptions.NoCount;
  114.  
  115. PredicateSetStatement noCountOn = new PredicateSetStatement();
  116. noCountOn.IsOn = true;
  117. noCountOn.Options = SetOptions.NoCount;
  118. InsertStatement batchCompleteInsert = CreateBatchCompleteInsert(batchId, batchDescription);
  119. statementBlock.StatementList.Statements.Add(noCountOn);
  120. statementBlock.StatementList.Statements.Add(batchCompleteInsert);
  121. statementBlock.StatementList.Statements.Add(noCountOff);
  122.  
  123. // Remove all the statements from the batch (they are now in the if block) and add the if statement
  124. // as the sole statement in the batch
  125. batch.Statements.Clear();
  126. batch.Statements.Add(ifBatchNotExecutedStatement);
  127.  
  128. // Next batch
  129. batchId++;
  130. #endregion
  131. }
  132.  
  133. #endregion
  134. }
  135.  
  136. // if we found steps that required processing, set up a temporary table to track the work that you are doing
  137. if (beforePreDeploy != null)
  138. {
  139. #region Additional Post-Processing Steps
  140. // Declare a SqlCmd variables.
  141. //
  142. // CompletedBatches variable - defines the name of the table in tempdb that will track
  143. // all the completed batches. The temporary table's name has the target database name and
  144. // a guid embedded in it so that:
  145. // * Multiple deployment scripts targeting different DBs on the same server
  146. // * Failed deployments with old tables do not conflict with more recent deployments
  147. //
  148. // TotalBatchCount variable - the total number of batches surrounded by if statements. Using this
  149. // variable pre/post deployment scripts can also use the CompletedBatches table to make their
  150. // script rerunnable if there is an error during execution
  151. StringBuilder sqlcmdVars = new StringBuilder();
  152. sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, CompletedBatchesSqlCmd,
  153. context.Options.TargetDatabaseName, Guid.NewGuid().ToString("D"));
  154. sqlcmdVars.AppendLine();
  155. sqlcmdVars.AppendFormat(CultureInfo.InvariantCulture, TotalBatchCountSqlCmd, batchId);
  156.  
  157. DeploymentScriptStep completedBatchesSetVarStep = new DeploymentScriptStep(sqlcmdVars.ToString());
  158. base.AddBefore(context.PlanHandle, beforePreDeploy, completedBatchesSetVarStep);
  159.  
  160. // Create the temporary table we will use to track the work that we are doing
  161. DeploymentScriptStep createStatusTableStep = new DeploymentScriptStep(CreateCompletedBatchesTable);
  162. base.AddBefore(context.PlanHandle, beforePreDeploy, createStatusTableStep);
  163. #endregion
  164. }
  165.  
  166. // Cleanup and drop the table
  167. DeploymentScriptStep dropStep = new DeploymentScriptStep(DropCompletedBatchesTable);
  168. base.AddAfter(context.PlanHandle, context.PlanHandle.Tail, dropStep);
  169. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement