Add Agent Job and Job Step request handlers (#635)

* Stage changes

* Fix update job request handler

* WIP

* Additional agent handler updates

* Setup agent job step create test

* Fix Step update handler
This commit is contained in:
Karl Burtram
2018-06-13 10:02:25 -07:00
committed by GitHub
parent 7c1f78a678
commit 8dda34c95a
52 changed files with 705 additions and 619 deletions

View File

@@ -7,12 +7,13 @@ using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{
@@ -189,51 +190,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
}
}
/// <summary>
/// Create a data container object
/// </summary>
/// <param name="connInfo">connection info</param>
/// <param name="databaseExists">flag indicating whether to create taskhelper for existing database or not</param>
internal static CDataContainer CreateDataContainer(ConnectionInfo connInfo, bool databaseExists = false)
{
XmlDocument xmlDoc = CreateDataContainerDocument(connInfo, databaseExists);
CDataContainer dataContainer;
// add alternate port to server name property if provided
var connectionDetails = connInfo.ConnectionDetails;
string serverName = !connectionDetails.Port.HasValue
? connectionDetails.ServerName
: string.Format("{0},{1}", connectionDetails.ServerName, connectionDetails.Port.Value);
// check if the connection is using SQL Auth or Integrated Auth
//TODO: ConnectionQueue try to get an existing connection (ConnectionQueue)
if (string.Equals(connectionDetails.AuthenticationType, "SqlLogin", StringComparison.OrdinalIgnoreCase))
{
var passwordSecureString = BuildSecureStringFromPassword(connectionDetails.Password);
dataContainer = new CDataContainer(
CDataContainer.ServerType.SQL,
serverName,
false,
connectionDetails.UserName,
passwordSecureString,
connectionDetails.DatabaseName,
xmlDoc.InnerXml);
}
else
{
dataContainer = new CDataContainer(
CDataContainer.ServerType.SQL,
serverName,
true,
null,
null,
connectionDetails.DatabaseName,
xmlDoc.InnerXml);
}
return dataContainer;
}
/// <summary>
/// Create database task helper
/// </summary>
@@ -242,65 +198,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
/// <returns></returns>
internal static DatabaseTaskHelper CreateDatabaseTaskHelper(ConnectionInfo connInfo, bool databaseExists = false)
{
var dataContainer = CreateDataContainer(connInfo, databaseExists);
var dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists);
var taskHelper = new DatabaseTaskHelper(dataContainer);
return taskHelper;
}
internal static System.Security.SecureString BuildSecureStringFromPassword(string password) {
var passwordSecureString = new System.Security.SecureString();
if (password != null) {
foreach (char c in password) {
passwordSecureString.AppendChar(c);
}
}
return passwordSecureString;
}
/// <summary>
/// Create data container document
/// </summary>
/// <param name="connInfo">connection info</param>
/// <param name="databaseExists">flag indicating whether to create document for existing database or not</param>
/// <returns></returns>
private static XmlDocument CreateDataContainerDocument(ConnectionInfo connInfo, bool databaseExists)
{
string xml = string.Empty;
if (!databaseExists)
{
xml =
string.Format(@"<?xml version=""1.0""?>
<formdescription><params>
<servername>{0}</servername>
<connectionmoniker>{0} (SQLServer, user = {1})</connectionmoniker>
<servertype>sql</servertype>
<urn>Server[@Name='{0}']</urn>
<itemtype>Database</itemtype>
</params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(),
connInfo.ConnectionDetails.UserName);
}
else
{
xml =
string.Format(@"<?xml version=""1.0""?>
<formdescription><params>
<servername>{0}</servername>
<connectionmoniker>{0} (SQLServer, user = {1})</connectionmoniker>
<servertype>sql</servertype>
<urn>Server[@Name='{0}']</urn>
<database>{2}</database>
</params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(),
connInfo.ConnectionDetails.UserName,
connInfo.ConnectionDetails.DatabaseName);
}
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
return xmlDoc;
}
/// <summary>
/// Handles a create login request
/// </summary>

View File

@@ -9,8 +9,9 @@ using System.Collections.Generic;
using System.Globalization;
using Microsoft.SqlServer.Diagnostics.STrace;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.Win32;
using SizeUnits = Microsoft.SqlTools.ServiceLayer.Admin.DbSize.SizeUnits;
using SizeUnits = Microsoft.SqlTools.ServiceLayer.Management.DbSize.SizeUnits;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -20,6 +20,7 @@ using System.Globalization;
using System.Data.SqlClient;
using System.Collections.Generic;
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -17,6 +17,7 @@ using System.Data.SqlClient;
using System.Collections.Generic;
using System.Diagnostics;
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{
@@ -117,8 +118,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
/// </remarks>
public DatabaseData(CDataContainer context)
{
this.name = String.Empty;
this.owner = String.Empty;
this.name = string.Empty;
this.owner = string.Empty;
this.restrictAccess = DatabaseUserAccess.Multiple;
this.isReadOnly = false;
this.databaseState = DatabaseStatus.Normal;
@@ -176,7 +177,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
this.targetRecoveryTime = 0;
ResourceManager manager = new ResourceManager("Microsoft.SqlTools.ServiceLayer.Localization.SR", typeof(DatabasePrototype).GetAssembly());
//in katmai var decimal going to be true by default

View File

@@ -10,6 +10,7 @@ using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -7,6 +7,7 @@ using System.ComponentModel;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -10,6 +10,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Diagnostics;
using System.Collections.Generic;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -5,6 +5,7 @@
using System.ComponentModel;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -10,6 +10,7 @@ using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Diagnostics;
using System.Collections.Generic;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -6,6 +6,7 @@
using System.ComponentModel;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Admin
{

View File

@@ -11,6 +11,7 @@ using System.Linq;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
namespace Microsoft.SqlTools.ServiceLayer.Admin

View File

@@ -6,6 +6,7 @@
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.Utility;
using System;
using System.Collections;

View File

@@ -6,9 +6,11 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
@@ -326,7 +328,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Create);
ConfigAction.Create,
RunType.RunNow);
await requestContext.SendResult(new CreateAgentJobStepResult()
{
@@ -337,14 +340,32 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
internal async Task HandleUpdateAgentJobStepRequest(UpdateAgentJobStepParams parameters, RequestContext<UpdateAgentJobStepResult> requestContext)
{
UpdateAgentJobStepResult result = new UpdateAgentJobStepResult();
await requestContext.SendResult(result);
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Update,
RunType.RunNow);
await requestContext.SendResult(new UpdateAgentJobStepResult()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task HandleDeleteAgentJobStepRequest(DeleteAgentJobStepParams parameters, RequestContext<ResultStatus> requestContext)
{
ResultStatus result = new ResultStatus();
await requestContext.SendResult(result);
Tuple<bool, string> result = await ConfigureAgentJobStep(
parameters.OwnerUri,
parameters.Step,
ConfigAction.Drop,
RunType.RunNow);
await requestContext.SendResult(new ResultStatus()
{
Success = result.Item1,
ErrorMessage = result.Item2
});
}
internal async Task<Tuple<bool, string>> ConfigureAgentJob(
@@ -362,10 +383,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ownerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(
connInfo,
databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(
dataContainer.Server.Name.ToUpper(),
jobInfo.Name);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", jobInfo.JobId);
param.SetParam("jobid", string.Empty);
var jobData = new JobData(dataContainer, jobInfo);
using (JobActions jobActions = new JobActions(dataContainer, jobData, configAction))
@@ -386,13 +416,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
internal async Task<Tuple<bool, string>> ConfigureAgentJobStep(
string ownerUri,
AgentJobStepInfo stepInfo,
ConfigAction configAction)
ConfigAction configAction,
RunType runType)
{
return await Task<Tuple<bool, string>>.Run(() =>
{
try
{
if (string.IsNullOrWhiteSpace(stepInfo.JobId))
if (string.IsNullOrWhiteSpace(stepInfo.JobName))
{
return new Tuple<bool, string>(false, "JobId cannot be null");
}
@@ -402,17 +433,25 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ownerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(
connInfo,
databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(
dataContainer.Server.Name.ToUpper(),
stepInfo.JobName);
dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("job", string.Empty);
param.SetParam("jobid", stepInfo.JobId);
param.SetParam("script", stepInfo.Script);
param.SetParam("scriptName", stepInfo.ScriptName);
param.SetParam("jobid", string.Empty);
var jobData = new JobData(dataContainer);
using (var jobStep = new JobStepsActions(dataContainer, jobData))
using (var jobStep = new JobStepsActions(dataContainer, jobData, stepInfo, configAction))
{
jobStep.CreateJobStep();
var executionHandler = new ExecutonHandler(jobStep);
executionHandler.RunNow(runType, this);
}
return new Tuple<bool, string>(true, string.Empty);
@@ -425,6 +464,38 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
});
}
public XmlDocument CreateJobXmlDocument(string svrName, string jobName)
{
// XML element strings
const string XmlFormDescElementName = "formdescription";
const string XmlParamsElementName = "params";
const string XmlJobElementName = "job";
const string XmlUrnElementName = "urn";
const string UrnFormatStr = "Server[@Name='{0}']/JobServer[@Name='{0}']/Job[@Name='{1}']";
// Write out XML.
StringWriter textWriter = new StringWriter();
XmlTextWriter xmlWriter = new XmlTextWriter(textWriter);
xmlWriter.WriteStartElement(XmlFormDescElementName);
xmlWriter.WriteStartElement(XmlParamsElementName);
xmlWriter.WriteElementString(XmlJobElementName, jobName);
xmlWriter.WriteElementString(XmlUrnElementName, string.Format(UrnFormatStr, svrName, jobName));
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
xmlWriter.Close();
// Create an XML document.
XmlDocument doc = new XmlDocument();
XmlTextReader rdr = new XmlTextReader(new System.IO.StringReader(textWriter.ToString()));
rdr.MoveToContent();
doc.LoadXml(rdr.ReadOuterXml());
return doc;
}
#endregion // "Jobs Handlers"
#region "Alert Handlers"
@@ -446,7 +517,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
if (connInfo != null)
{
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
AlertCollection alerts = dataContainer.Server.JobServer.Alerts;
}
@@ -502,7 +573,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{
if (connInfo != null && ValidateAgentAlertInfo(alert))
{
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
@@ -531,7 +602,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
AgentAlertInfo alert = parameters.Alert;
if (connInfo != null && ValidateAgentAlertInfo(alert))
{
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("alert", alert.JobName);
@@ -572,7 +643,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
out connInfo);
AgentOperatorInfo operatorInfo = parameters.Operator;
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("operator", operatorInfo.Name);
@@ -662,7 +733,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ownerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
STParameters param = new STParameters(dataContainer.Document);
param.SetParam("proxyaccount", accountName);

View File

@@ -13,6 +13,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent.Contracts
{
public string JobId { get; set; }
public string JobName { get; set; }
public string Script { get; set; }
public string ScriptName { get; set; }

View File

@@ -49,13 +49,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{
base.DoPreProcessExecution(runType, out executionResult);
this.data.ApplyChanges(creating: true);
if (!IsScripting(runType))
{
this.DataContainer.SqlDialogSubject = this.data.Job;
}
if (this.configAction == ConfigAction.Drop)
{
if (this.data.Job != null)
{
this.data.Job.DropIfExists();
}
}
else
{
this.data.ApplyChanges(creating: this.configAction == ConfigAction.Create);
if (!IsScripting(runType))
{
this.DataContainer.SqlDialogSubject = this.data.Job;
}
}
return false;
}
}
}
}

View File

@@ -16,6 +16,7 @@ using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlTools.ServiceLayer.Admin;
using SMO = Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{

View File

@@ -14,6 +14,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
using SMO = Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Agent
@@ -1139,9 +1140,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
else
{
// just lookup the original object
STParameters parameters = new STParameters(this.context.Document);
string urn = string.Empty;
job = this.context.Server.GetSmoObject(this.urn) as Job;
job = this.Job;
}
if (!this.IsReadOnly)

View File

@@ -15,8 +15,10 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
using SMO = Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
internal class JobSchedulesData

View File

@@ -17,6 +17,7 @@ using System.Text;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{

View File

@@ -15,7 +15,6 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using SMO = Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
internal class JobStepData
@@ -45,26 +44,32 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// Original name of this step
/// </summary>
string originalName;
/// <summary>
/// Current name
/// </summary>
string currentName;
/// <summary>
/// Current step id
/// </summary>
int id;
/// <summary>
/// Original step id
/// </summary>
int originalId;
/// <summary>
/// Subsystem that will execute this step
/// </summary>
AgentSubSystem subSystem;
/// <summary>
/// action to take if the step fails
/// </summary>
StepCompletionAction failureAction;
/// <summary>
/// Action to take if the step succeeds
/// </summary>
@@ -175,6 +180,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return jobStep;
}
}
/// <summary>
/// Server version
/// </summary>
@@ -185,6 +191,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return this.parent.Version;
}
}
/// <summary>
/// indicates whether the job exists on the server
/// </summary>
@@ -237,7 +244,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
#endregion
#region Properties for Job Step
public String Name
public string Name
{
get
{
@@ -248,7 +255,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.currentName = value.Trim();
}
}
public String Command
public string Command
{
get
{
@@ -274,7 +282,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.commandExecutionSuccessCode = value;
}
}
public String DatabaseName
public string DatabaseName
{
get
{
@@ -287,7 +295,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.databaseName = value;
}
}
public String DatabaseUserName
public string DatabaseUserName
{
get
{
@@ -300,7 +308,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.databaseUserName = value;
}
}
public String Server
public string Server
{
get
{
@@ -706,7 +714,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.successStep = null;
this.successStepId = -1;
this.priority = OSRunPriority.Normal;
this.outputFileName = String.Empty;
this.outputFileName = string.Empty;
this.appendToLogFile = false;
this.appendToStepHist = false;
this.writeLogToTable = false;
@@ -1027,15 +1035,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
this.failStep = step;
}
#endregion
}
}

View File

@@ -13,6 +13,7 @@ using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{

View File

@@ -4,168 +4,88 @@
//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Agent.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Agent
{
/// <summary>
/// Summary description for JobSteps.
/// JobStepsActions
/// </summary>
internal class JobStepsActions : ManagementActionBase
{
private bool validated = true;
private JobStepData data;
private JobData jobData;
private JobData data;
public JobStepsActions(CDataContainer dataContainer, JobData data)
public JobStepsActions(
CDataContainer dataContainer,
JobData jobData,
AgentJobStepInfo stepInfo,
ConfigAction configAction)
{
this.DataContainer = dataContainer;
this.data = data;
this.jobData = jobData;
if (configAction == ConfigAction.Update)
{
JobStep jobStep = GetJobStep(this.jobData, stepInfo.StepName);
this.data = new JobStepData(jobStep, jobData.JobSteps);
}
else
{
this.data = new JobStepData(jobData.JobSteps);
}
// load properties from AgentJobStepInfo
this.data.ID = stepInfo.Id;
this.data.Name = stepInfo.StepName;
this.data.Command = stepInfo.Script;
}
#region ISupportValidation
/// <summary>
/// Validate the Job step data.
/// This is limited to two checks
/// 1. See if all steps are reachable
/// 2. If we are editing rather than creating check to see if the last steps completion
/// action will change from GoToNext to QuitWithSuccess.
/// </summary>
/// <returns>true if the checks passed, or the user has ok the warning</returns>
public bool Validate()
protected override bool DoPreProcessExecution(RunType runType, out ExecutionMode executionResult)
{
// Only validate once after the user has made changes. Validate() is called when the
// user navigates away from the JobSteps page, and if they navigate back and then out
// again they'd be prompted twice. This annoys our users.
if (this.validated)
base.DoPreProcessExecution(runType, out executionResult);
// Make sure the job step name is not blank.
if (this.data.Name == null || this.data.Name.Length == 0)
{
return true;
throw new Exception(SR.JobStepNameCannotBeBlank);
}
bool valid = true;
// Get the unreachable steps
List<JobStepData> unreachableSteps = this.data.JobSteps.FindUnreachableJobSteps();
// see if the last step success completion action will change
bool lastStepWillChange = this.data.JobSteps.CheckIfLastStepCompletionActionWillChange();
// warning message
StringBuilder warningMessage = new StringBuilder();
// if there are unreachable steps, add the warning and each problematic step
if (unreachableSteps.Count > 0)
// Check to make sure that the user has not entered a job step name that already exists.
for (int stepIndex = 0; stepIndex < this.data.Parent.Steps.Count; ++stepIndex)
{
warningMessage.AppendLine("JobSR.UnreachableStepHeader");
foreach (JobStepData jobStep in unreachableSteps)
// don't compare if the id's are the same.
if (data.ID != ((JobStepData)this.data.Parent.Steps[stepIndex]).ID && data.Name == ((JobStepData)this.data.Parent.Steps[stepIndex]).Name)
{
warningMessage.AppendLine("JobSR.UnreachableStepFormat(jobStep.ID, jobStep.Name)");
// Throw an error if the job step name already exists
throw new Exception(SR.JobStepNameAlreadyExists(this.data.Name));
}
warningMessage.AppendLine(string.Empty);
}
// add a warning if the last step will change
if (lastStepWillChange)
{
warningMessage.AppendLine("JobSR.LastStepSuccessWillChange");
warningMessage.AppendLine(string.Empty);
if (runType == RunType.RunNow)
{
this.data.ApplyChanges(this.jobData.Job);
}
// if anything was wrong tell the user and see if they are ok with it
if (warningMessage.Length > 0)
{
warningMessage.Append("JobSR.AreYouSure");
}
this.validated = valid;
return valid;
// regular execution always takes place
return true;
}
#endregion
// private void PopulateGrid(JobStepsData steps)
// {
// for (int i = 0; i < steps.Steps.Count; i++)
// {
// JobStepData step = steps.Steps[i] as JobStepData;
// if (step != null)
// {
// // add rows to the grid
// GridCellCollection row = new GridCellCollection();
// GridCell cell;
// // id
// cell = new GridCell(step.ID.ToString(CultureInfo.InvariantCulture));
// row.Add(cell);
// // step name
// cell = new GridCell(step.Name);
// row.Add(cell);
// // subsystem
// cell = new GridCell(JobStepSubSystems.LookupFriendlyName(step.SubSystem));
// row.Add(cell);
// // on success
// cell = new GridCell(GetFriendlyNameForAction(step.SuccessAction, step.SuccessStep));
// row.Add(cell);
// // on failure
// cell = new GridCell(GetFriendlyNameForAction(step.FailureAction, step.FailStep));
// row.Add(cell);
// this.jobStepList.AddRow(row);
// }
// }
// }
/// <summary>
/// Convert an action and it's target step to a localizable user friendly name
/// </summary>
/// <param name="action"></param>
/// <param name="targetStep"></param>
/// <returns></returns>
// private static string GetFriendlyNameForAction(StepCompletionAction action, JobStepData targetStep)
// {
// String friendlyName = String.Empty;
// // switch (action)
// // {
// // case StepCompletionAction.GoToNextStep:
// // friendlyName = JobSR.GotoNextStep;
// // break;
// // case StepCompletionAction.QuitWithFailure:
// // friendlyName = JobSR.QuitWithFailure;
// // break;
// // case StepCompletionAction.QuitWithSuccess:
// // friendlyName = JobSR.QuitWithSuccess;
// // break;
// // case StepCompletionAction.GoToStep:
// // STrace.Assert(targetStep != null, "Action type is goto step, but the target step is null");
// // if (targetStep != null)
// // {
// // friendlyName = JobSR.GotoStep(targetStep.ID, targetStep.Name);
// // }
// // break;
// // default:
// // STrace.Assert(false, "Unknown jobstep completion action");
// // break;
// // }
// return friendlyName;
// }
public void CreateJobStep()
private JobStep GetJobStep(JobData jobData, string stepName)
{
//JobStepData data = new JobStepData(this.data.JobSteps);
JobStepData data = this.data.JobSteps.Steps[0] as JobStepData;
JobStepPropertySheet jsProp = new JobStepPropertySheet(this.DataContainer, data);
jsProp.Init();
jsProp.Create();
JobStep jobStep = null;
if (jobData.Job != null)
{
const string UrnFormatStr = "Server[@Name='{0}']/JobServer[@Name='{0}']/Job[@Name='{1}']/Step[@Name='{2}']";
string serverName = this.DataContainer.Server.Name.ToUpper();
string urn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, stepName);
jobStep = jobData.Job.Parent.Parent.GetSmoObject(urn) as JobStep;
}
return jobStep;
}
}
}

View File

@@ -14,6 +14,7 @@ using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
using SMO = Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Agent

View File

@@ -9,18 +9,14 @@ using System.Collections;
using System.ComponentModel;
using Microsoft.SqlServer.Management.Smo.Agent;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlServer.Management.SqlManagerUI
{
/// <summary>
/// Summary description for JobsRefrencingScheduleForm.
/// </summary>
#if DEBUG || EXPOSE_MANAGED_INTERNALS
public
#else
internal
#endif
class JobsReferencingScheduleForm
public class JobsReferencingScheduleForm
{
#region UI Variables

View File

@@ -13,6 +13,7 @@ using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery

View File

@@ -5,6 +5,7 @@
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using System.Data.SqlClient;

View File

@@ -11,6 +11,7 @@ using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using SMO = Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery
{

View File

@@ -13,6 +13,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.Contracts;
using Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation;
using Microsoft.SqlTools.ServiceLayer.FileBrowser;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.TaskServices;
using Microsoft.SqlTools.Utility;

View File

@@ -4341,6 +4341,14 @@ namespace Microsoft.SqlTools.ServiceLayer
}
}
public static string JobStepNameCannotBeBlank
{
get
{
return Keys.GetString(Keys.JobStepNameCannotBeBlank);
}
}
public static string ConnectionServiceListDbErrorNotConnected(string uri)
{
return Keys.GetString(Keys.ConnectionServiceListDbErrorNotConnected, uri);
@@ -4576,6 +4584,16 @@ namespace Microsoft.SqlTools.ServiceLayer
return Keys.GetString(Keys.OperatorProperties, operatorName);
}
public static string JobAlreadyExists(string jobName)
{
return Keys.GetString(Keys.JobAlreadyExists, jobName);
}
public static string JobStepNameAlreadyExists(string jobName)
{
return Keys.GetString(Keys.JobStepNameAlreadyExists, jobName);
}
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Keys
{
@@ -6342,6 +6360,15 @@ namespace Microsoft.SqlTools.ServiceLayer
public const string CategoryDataCollector = "CategoryDataCollector";
public const string JobAlreadyExists = "JobAlreadyExists";
public const string JobStepNameCannotBeBlank = "JobStepNameCannotBeBlank";
public const string JobStepNameAlreadyExists = "JobStepNameAlreadyExists";
private Keys()
{ }

View File

@@ -2508,4 +2508,18 @@
<value>Data Collector</value>
<comment></comment>
</data>
<data name="JobAlreadyExists" xml:space="preserve">
<value>A job named '{0}' already exists. Enter a unique name for the job.</value>
<comment>.
Parameters: 0 - jobName (string) </comment>
</data>
<data name="JobStepNameCannotBeBlank" xml:space="preserve">
<value>The name of the job step cannot be blank.</value>
<comment></comment>
</data>
<data name="JobStepNameAlreadyExists" xml:space="preserve">
<value>There is already a step named '{0}' for this job. You must specify a different name.</value>
<comment>.
Parameters: 0 - jobName (string) </comment>
</data>
</root>

View File

@@ -1067,4 +1067,6 @@ CategoryLogShipping = Log Shipping
CategoryDBEngineTuningAdvisor = Database Engine Tuning Advisor
CategoryDataCollector = Data Collector
JobAlreadyExists(string jobName) = A job named '{0}' already exists. Enter a unique name for the job.
JobStepNameCannotBeBlank = The name of the job step cannot be blank.
JobStepNameAlreadyExists(string jobName) = There is already a step named '{0}' for this job. You must specify a different name.

View File

@@ -2978,6 +2978,23 @@
<target state="new">Data Collector</target>
<note></note>
</trans-unit>
<trans-unit id="JobAlreadyExists">
<source>A job named '{0}' already exists. Enter a unique name for the job.</source>
<target state="new">A job named '{0}' already exists. Enter a unique name for the job.</target>
<note>.
Parameters: 0 - jobName (string) </note>
</trans-unit>
<trans-unit id="JobStepNameCannotBeBlank">
<source>The name of the job step cannot be blank.</source>
<target state="new">The name of the job step cannot be blank.</target>
<note></note>
</trans-unit>
<trans-unit id="JobStepNameAlreadyExists">
<source>There is already a step named '{0}' for this job. You must specify a different name.</source>
<target state="new">There is already a step named '{0}' for this job. You must specify a different name.</target>
<note>.
Parameters: 0 - jobName (string) </note>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -14,7 +14,7 @@ using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>
/// Helper static class for the BrowseFolder dialog

View File

@@ -13,14 +13,15 @@ using System.IO;
using System.Reflection;
using System.Security;
using System.Xml;
using System.Xml.Linq;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Assembly = System.Reflection.Assembly;
using System.Xml.Linq;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>
/// CDataContainer
@@ -178,7 +179,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
throw new InvalidOperationException();
}
if (this.sqlCiWithConnection != null)
{
this.serverConnection = this.sqlCiWithConnection.ServerConnection;
@@ -323,7 +323,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
{
get
{
string result = String.Empty;
string result = string.Empty;
if (this.IsNewObject)
{
@@ -421,8 +421,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
return result;
}
}
/// <summary>
@@ -691,15 +689,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
if (serverType == ServerType.SQL)
{
//does some extra initialization
ApplyConnectionInfo(GetTempSqlConnectionInfoWithConnection(serverName, trusted, userName, password, databaseName), true);
// does some extra initialization
ApplyConnectionInfo(GetTempSqlConnectionInfoWithConnection(serverName, trusted, userName, password, databaseName), true);
//NOTE: ServerConnection property will constuct the object if needed
m_server = new Server(ServerConnection);
}
// NOTE: ServerConnection property will constuct the object if needed
m_server = new Server(ServerConnection);
}
else
{
throw new ArgumentException("SRError.UnknownServerType(serverType.ToString()), serverType");
throw new ArgumentException("SRError.UnknownServerType(serverType.ToString()), serverType");
}
if (xmlParameters != null)
@@ -774,13 +772,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
if (site != null)
{
//see if service provider supports INodeInformation interface from the object explorer
// see if service provider supports INodeInformation interface from the object explorer
try
{
//NOTE: we're trying to forcefully set connection information on the data container.
//If this code doesn't execute, then dc.Init call below will result in CDataContainer
//initializing its ConnectionInfo member with a new object contructed off the parameters
//in the XML doc [server name, user name etc]
// NOTE: we're trying to forcefully set connection information on the data container.
// If this code doesn't execute, then dc.Init call below will result in CDataContainer
// initializing its ConnectionInfo member with a new object contructed off the parameters
// in the XML doc [server name, user name etc]
IManagedConnection managedConnection = site.GetService(typeof(IManagedConnection)) as IManagedConnection;
if (managedConnection != null)
{
@@ -810,15 +808,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
/// <param name="doc"></param>
public virtual void Init(XmlDocument doc)
{
//First, we read the data from XML by calling LoadData
// First, we read the data from XML by calling LoadData
this.Document = doc;
LoadData();
//Second, create the rignt server and connection objects
// Second, create the rignt server and connection objects
if (this.serverType == ServerType.SQL)
{
//ensure that we have a valid ConnectionInfo
// ensure that we have a valid ConnectionInfo
if (ConnectionInfo == null)
{
throw new InvalidOperationException();
@@ -826,7 +824,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
if (m_server == null)
{
//NOTE: ServerConnection property will constuct the object if needed
// NOTE: ServerConnection property will constuct the object if needed
m_server = new Server(ServerConnection);
}
}
@@ -852,19 +850,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
param.SetDocument(m_doc);
// DEVNOTE: chrisze 02/25/03
// This is an ugly way to distinguish between different server types
// Maybe we should pass server type as one of the parameters?
//
bStatus = param.GetParam("servername", ref this.serverName);
if (!bStatus || this.serverName.Length == 0)
{
{
bStatus = param.GetParam("database", ref this.sqlceFilename);
if (bStatus && !String.IsNullOrEmpty(this.sqlceFilename))
bStatus = param.GetParam("database", ref this.sqlceFilename);
if (bStatus && !string.IsNullOrEmpty(this.sqlceFilename))
{
this.serverType = ServerType.SQLCE;
}
@@ -880,15 +874,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
}
else
{
//OK, let's see if <servertype> was specified in the parameters. It it was, use
//it to double check that it is SQL
// OK, let's see if <servertype> was specified in the parameters. It it was, use
// it to double check that it is SQL
string specifiedServerType = "";
bStatus = param.GetParam("servertype", ref specifiedServerType);
if (bStatus)
{
if (specifiedServerType != null && "sql" != specifiedServerType.ToLowerInvariant())
{
this.serverType = ServerType.UNKNOWN;//we know only about 3 types, and 2 of them were excluded by if branch above
this.serverType = ServerType.UNKNOWN; // we know only about 3 types, and 2 of them were excluded by if branch above
}
else
{
@@ -902,7 +896,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
}
// Ensure there is no password in the XML document
string temp = String.Empty;
string temp = string.Empty;
if (param.GetParam("password", ref temp))
{
temp = null;
@@ -955,7 +949,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
object result = GetDocumentPropertyValue(propertyName);
if (result == null)
{
result = String.Empty;
result = string.Empty;
}
return (string)result;
@@ -993,7 +987,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
}
}
#endregion
#region Private helpers
@@ -1004,7 +997,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
private void InitializeObjectNameAndSchema()
{
string documentUrn = this.GetDocumentPropertyString("urn");
if (documentUrn.Length != 0)
{
Urn urn = new Urn(documentUrn);
@@ -1060,8 +1052,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
/// <param name="sender"></param>
/// <param name="e"></param>
private void OnSqlConnectionClosed(object sender, EventArgs e)
{
//nothing - per MRaheem we'll let user deal with this situation
{
}
/// <summary>
@@ -1075,12 +1066,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
this.connectionInfo = ci;
this.ownConnection = ownConnection;
//cache the cast value. It is OK that it is null for non SQL types
// cache the cast value. It is OK that it is null for non SQL types
this.sqlCiWithConnection = ci as SqlConnectionInfoWithConnection;
if (this.sqlCiWithConnection != null)
{
//we want to be notified if it is closed
// we want to be notified if it is closed
this.sqlCiWithConnection.ConnectionClosed += new EventHandler(OnSqlConnectionClosed);
}
}
@@ -1212,5 +1203,112 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
}
#endregion
/// <summary>
/// Create a data container object
/// </summary>
/// <param name="connInfo">connection info</param>
/// <param name="databaseExists">flag indicating whether to create taskhelper for existing database or not</param>
internal static CDataContainer CreateDataContainer(
ConnectionInfo connInfo,
bool databaseExists = false,
XmlDocument containerDoc = null)
{
if (containerDoc == null)
{
containerDoc = CreateDataContainerDocument(connInfo, databaseExists);
}
CDataContainer dataContainer;
// add alternate port to server name property if provided
var connectionDetails = connInfo.ConnectionDetails;
string serverName = !connectionDetails.Port.HasValue
? connectionDetails.ServerName
: string.Format("{0},{1}", connectionDetails.ServerName, connectionDetails.Port.Value);
// check if the connection is using SQL Auth or Integrated Auth
// TODO: ConnectionQueue try to get an existing connection (ConnectionQueue)
if (string.Equals(connectionDetails.AuthenticationType, "SqlLogin", StringComparison.OrdinalIgnoreCase))
{
var passwordSecureString = BuildSecureStringFromPassword(connectionDetails.Password);
dataContainer = new CDataContainer(
CDataContainer.ServerType.SQL,
serverName,
false,
connectionDetails.UserName,
passwordSecureString,
connectionDetails.DatabaseName,
containerDoc.InnerXml);
}
else
{
dataContainer = new CDataContainer(
CDataContainer.ServerType.SQL,
serverName,
true,
null,
null,
connectionDetails.DatabaseName,
containerDoc.InnerXml);
}
return dataContainer;
}
internal static System.Security.SecureString BuildSecureStringFromPassword(string password) {
var passwordSecureString = new System.Security.SecureString();
if (password != null) {
foreach (char c in password) {
passwordSecureString.AppendChar(c);
}
}
return passwordSecureString;
}
/// <summary>
/// Create data container document
/// </summary>
/// <param name="connInfo">connection info</param>
/// <param name="databaseExists">flag indicating whether to create document for existing database or not</param>
/// <returns></returns>
private static XmlDocument CreateDataContainerDocument(ConnectionInfo connInfo, bool databaseExists)
{
string xml = string.Empty;
if (!databaseExists)
{
xml =
string.Format(@"<?xml version=""1.0""?>
<formdescription><params>
<servername>{0}</servername>
<connectionmoniker>{0} (SQLServer, user = {1})</connectionmoniker>
<servertype>sql</servertype>
<urn>Server[@Name='{0}']</urn>
<itemtype>Database</itemtype>
</params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(),
connInfo.ConnectionDetails.UserName);
}
else
{
xml =
string.Format(@"<?xml version=""1.0""?>
<formdescription><params>
<servername>{0}</servername>
<connectionmoniker>{0} (SQLServer, user = {1})</connectionmoniker>
<servertype>sql</servertype>
<urn>Server[@Name='{0}']</urn>
<database>{2}</database>
</params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(),
connInfo.ConnectionDetails.UserName,
connInfo.ConnectionDetails.DatabaseName);
}
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
return xmlDoc;
}
}
}

View File

@@ -9,7 +9,7 @@ using System.Linq;
using System.Text;
using Microsoft.SqlServer.Management.Common;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>
/// Helper class to describe the size of an Azure database

View File

@@ -111,12 +111,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// <summary>
/// handler that we delegate execution related tasks to
/// </summary>
private ExecutionHandlerDelegate panelExecutionHandler;
/// <summary>
/// class that describes available views
/// </summary>
private ISqlControlCollection viewsHolder;
private ExecutionHandlerDelegate executionHandlerDelegate;
/// <summary>
/// class that describes available views that is also aware of execution
@@ -133,11 +128,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// </summary>
private StringBuilder script;
/// <summary>
/// index of the panel that is being executed
/// </summary>
private int currentlyExecutingPanelIndex;
/// <summary>
/// creates instance of the class and returns service provider that aggregates the provider
/// provider with extra services
@@ -152,7 +142,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
public ExecutonHandler(IExecutionAwareManagementAction managementAction)
{
this.managementAction = managementAction;
this.panelExecutionHandler = new ExecutionHandlerDelegate(managementAction);
this.executionHandlerDelegate = new ExecutionHandlerDelegate(managementAction);
}
#region public interface
@@ -194,7 +184,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
// reset some internal vars
this.executionResult = ExecutionMode.Failure;
this.currentlyExecutingPanelIndex = -1; // will become 0 if we're executing on view by view basis
// ensure that we have valid StringBulder for scripting
if (IsScripting(runType))
@@ -220,7 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
// NOTE: post process action is done in finally block below
// start executing
this.executionResult = this.panelExecutionHandler.Run(runType, sender);
this.executionResult = this.executionHandlerDelegate.Run(runType, sender);
}
#region error handling
@@ -238,7 +227,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
}
catch (Exception e)
{
ProcessExceptionDuringExecution(e, this.currentlyExecutingPanelIndex);
ProcessExceptionDuringExecution(e);
return;
}
@@ -272,7 +261,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
//otherwise do cancel ourselves
// if everything goes OK, Run() method will return with Cancel result
this.panelExecutionHandler.Cancel(sender);
this.executionHandlerDelegate.Cancel(sender);
}
/// <summary>
@@ -333,10 +322,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// helper function that is called when we caught an exception during execution
/// </summary>
/// <param name="e"></param>
/// <param name="failedViewIndex">-1 indicates that we don't know</param>
private void ProcessExceptionDuringExecution(Exception e, int failedViewIndex)
private void ProcessExceptionDuringExecution(Exception ex)
{
//show the error
// show the error
this.executionResult = ExecutionMode.Failure;
}
#endregion

View File

@@ -8,7 +8,7 @@ using System.Collections;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>

View File

@@ -33,6 +33,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// </summary>
private IServiceProvider serviceProvider;
/// <summary>
/// execution mode by default for now is success
/// </summary>
private ExecutionMode m_executionMode = ExecutionMode.Success;
/// <summary>
/// data container with initialization-related information
/// </summary>
@@ -52,7 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
//property by the initialization code
private ServerConnection serverConnection;
private ExecutionHandlerDelegate cachedPanelExecutionHandler;
private ExecutionHandlerDelegate cachedExecutionHandlerDelegate;
#endregion
@@ -71,8 +76,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
void IDisposable.Dispose()
{
//BUGBUG - do we need finalizer
Dispose(true);//call protected virtual method
// BUGBUG - do we need finalizer
Dispose(true); // call protected virtual method
}
/// <summary>
@@ -103,27 +108,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
throw new ArgumentNullException("sp");
}
//allow to be sited only once
// allow to be sited only once
if (this.serviceProvider == null)
{
//cache the service provider
// cache the service provider
this.serviceProvider = sp;
//call protected virtual method to enable derived classes to do initialization
//OnHosted();
// call protected virtual method to enable derived classes to do initialization
// OnHosted();
}
}
#endregion
#region IExecutionAwareSqlControlCollection implementation
#region IExecutionAwareManagementAction implementation
/// <summary>
/// called before dialog's host executes actions on all panels in the dialog one by one.
/// called before management action executes onRun method.
/// If something fails inside this function and the execution should be aborted,
/// it can either raise an exception [in which case the framework will show message box with exception text]
/// it can either raise an exception [in which case the framework will fail with exception text]
/// or set executionResult out parameter to be ExecutionMode.Failure
/// NOTE: it might be called from worker thread
/// </summary>
/// <param name="executionInfo">information about execution action</param>
/// <param name="executionResult">result of the execution</param>
@@ -149,10 +153,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
}
}
if (DataContainer != null)
if (this.DataContainer != null)
{
// we take over execution here. We substitute the server here for SQL containers
if (DataContainer.ContainerServerType == CDataContainer.ServerType.SQL)
if (this.DataContainer.ContainerServerType == CDataContainer.ServerType.SQL)
{
ExecuteForSql(executionInfo, out executionResult);
return false; // execution of the entire action was done here
@@ -199,13 +203,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
get
{
//by default we own it
// by default we own it
return true;
}
}
/// <summary>
/// called by IExecutionAwareSqlControlCollection.PreProcessExecution to enable derived
/// called by IExecutionAwareManagementAction.PreProcessExecution to enable derived
/// classes to take over execution of the dialog and do entire execution in this method
/// rather than having the framework to execute dialog views one by one.
///
@@ -226,8 +230,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
}
/// <summary>
/// called after dialog's host executes actions on all panels in the dialog one by one
/// NOTE: it might be called from worker thread
/// called after management action executes onRun method.
/// </summary>
/// <param name="executionMode">result of the execution</param>
/// <param name="runType">type of execution</param>
@@ -235,34 +238,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
//nothing to do in the base class
}
/// <summary>
/// called before dialog's host executes OnReset method on all panels in the dialog one by one
/// NOTE: it might be called from worker thread
/// </summary>
/// <returns>
/// true if regular execution should take place, false if everything
/// has been done by this function
/// </returns>
/// <returns></returns>
protected virtual bool DoPreProcessReset()
{
if ((this.dataContainer != null) && this.dataContainer.IsNewObject)
{
this.dataContainer.Reset();
}
return true;
}
/// <summary>
/// called after dialog's host executes OnReset method on all panels in the dialog one by one
/// NOTE: it might be called from worker thread
/// </summary>
protected virtual void DoPostProcessReset()
{
//nothing in the base class
}
/// <summary>
/// Called to intercept scripting operation
@@ -344,7 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
if (DoPreProcessExecution(runType, out executionResult))
{
// true return value means that we need to do execution ourselves
executionResult = PanelExecutionHandler.Run(runType, this);
executionResult = ExecutionHandlerDelegate.Run(runType, this);
}
return executionResult;
@@ -446,18 +421,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
private void ExecuteForSql(PreProcessExecutionInfo executionInfo, out ExecutionMode executionResult)
{
Microsoft.SqlServer.Management.Smo.Server oldServer = null;
if (NeedToSwitchServer)
if (this.NeedToSwitchServer)
{
// We use a new instance of the SMO Server object every time we script
// so that any changes that are made to the SMO server while scripting are
// not kept when the script operation is completed.
oldServer = DataContainer.Server;
oldServer = this.DataContainer.Server;
//BUGBUG - see if we can use copy ctor instead
DataContainer.Server = new Microsoft.SqlServer.Management.Smo.Server(DataContainer.ServerConnection);
// BUGBUG - see if we can use copy ctor instead
this.DataContainer.Server = new Microsoft.SqlServer.Management.Smo.Server(DataContainer.ServerConnection);
}
string szScript = null;
string script = null;
bool isScripting = IsScripting(executionInfo.RunType);
var executionModeOriginal = GetServerConnectionForScript().SqlExecutionModes;
// For Azure the ExecutionManager is different depending on which ExecutionManager
@@ -499,7 +474,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
if (executionResult == ExecutionMode.Success)
{
szScript = BuildSqlScript();
script = BuildSqlScript();
}
}
}
@@ -524,13 +499,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
//see if we need to restore the server
if (oldServer != null)
{
DataContainer.Server = oldServer;
this.DataContainer.Server = oldServer;
}
}
if (isScripting)
{
executionInfo.Script = szScript;
executionInfo.Script = script;
}
}
@@ -538,112 +513,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// returns internal helper class that we delegate execution of the panels one by one when
/// we do it ourselves during scripting
/// </summary>
private ExecutionHandlerDelegate PanelExecutionHandler
private ExecutionHandlerDelegate ExecutionHandlerDelegate
{
get
{
if (this.cachedPanelExecutionHandler == null)
if (this.cachedExecutionHandlerDelegate == null)
{
this.cachedPanelExecutionHandler = new ExecutionHandlerDelegate(this);
this.cachedExecutionHandlerDelegate = new ExecutionHandlerDelegate(this);
}
return this.cachedPanelExecutionHandler;
return this.cachedExecutionHandlerDelegate;
}
}
// #region ICustomAttributeProvider
// object[] System.Reflection.ICustomAttributeProvider.GetCustomAttributes(bool inherit)
// {
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
// //to the derived classes
// return GetMergedArray(DoGetCustomAttributes(inherit), GetType().GetCustomAttributes(inherit));
// }
// object[] System.Reflection.ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit)
// {
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
// //to the derived classes
// return GetMergedArray(DoGetCustomAttributes(attributeType, inherit),
// GetType().GetCustomAttributes(attributeType, inherit));
// }
// bool System.Reflection.ICustomAttributeProvider.IsDefined(Type attributeType, bool inherit)
// {
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
// //to the derived classes
// if (!DoIsDefined(attributeType, inherit))
// {
// return GetType().IsDefined(attributeType, inherit);
// }
// else
// {
// return true;
// }
// }
// #endregion
// #region ICustomAttributeProvider helpers
// protected virtual object[] DoGetCustomAttributes(bool inherit)
// {
// return GetMergedArray(DoGetCustomAttributes(typeof(ScriptTypeAttribute), inherit),
// DoGetCustomAttributes(typeof(DialogScriptableAttribute), inherit));
// }
// protected virtual object[] DoGetCustomAttributes(Type attributeType, bool inherit)
// {
// //if the type specifies this attribute, we don't bother - it overrides
// //our behavior
// object[] typeAttribs = GetType().GetCustomAttributes(attributeType, inherit);
// if (typeAttribs != null && typeAttribs.Length > 0)
// {
// return null;
// }
// //we expose default custom attribute for script type
// if (attributeType.Equals(typeof(ScriptTypeAttribute)))
// {
// string scriptType = ScriptType;
// if (scriptType != null)
// {
// return new object[] {new ScriptTypeAttribute(scriptType)};
// }
// else
// {
// return null;
// }
// }
// else if (attributeType.Equals(typeof(DialogScriptableAttribute)))
// {
// bool canScriptToWindow = true;
// bool canScriptToFile = true;
// bool canScriptToClipboard = true;
// bool canScriptToJob = true;
// GetScriptableOptions(out canScriptToWindow,
// out canScriptToFile,
// out canScriptToClipboard,
// out canScriptToJob);
// return new object[] {new DialogScriptableAttribute(canScriptToWindow,
// canScriptToFile,
// canScriptToClipboard,
// canScriptToJob)};
// }
// return null;
// }
// protected virtual bool DoIsDefined(Type attributeType, bool inherit)
// {
// return false;
// }
// /// <summary>
// /// detects whether script types are applicable for this dlg or not. By default
// /// the framework relies on DialogScriptableAttribute set on the dlg class and won't
// /// call this method if the attribute is specified
// /// By default we assume that all script types are enabled
// /// </summary>
// /// <param name="?"></param>
// /// <param name="?"></param>
// /// <param name="?"></param>
// protected virtual void GetScriptableOptions(out bool canScriptToWindow,
// out bool canScriptToFile,
// out bool canScriptToClipboard,
// out bool canScriptToJob)
// {
// canScriptToWindow = canScriptToFile = canScriptToClipboard = canScriptToJob = true;
// }
// #endregion
protected IServiceProvider ServiceProvider
{
get
@@ -656,35 +537,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
return this.serviceProvider;
}
}
// /// <summary>
// /// returns combination of the given 2 arrays
// /// </summary>
// /// <param name="array1"></param>
// /// <param name="array2"></param>
// /// <returns></returns>
// protected object[] GetMergedArray(object[] array1, object[] array2)
// {
// if (array1 == null)
// {
// return array2;
// }
// else if (array2 == null)
// {
// return array1;
// }
// else
// {
// object[] finalReturnValue = new object[array1.Length + array2.Length];
// array1.CopyTo(finalReturnValue, 0);
// array2.CopyTo(finalReturnValue, array1.Length);
// return finalReturnValue;
// }
// }
/// <summary>
/// execution mode by default for now is success
/// </summary>
private ExecutionMode m_executionMode = ExecutionMode.Success;
/// <summary>
/// execution mode accessor
@@ -737,7 +589,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// <param name="sender"></param>
public virtual string OnScript(object sender)
{
//redirect to the single scripting virtual method by default
// redirect to the single scripting virtual method by default
return Script();
}
@@ -758,7 +610,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
return null;
}
/// <summary>
/// performs custom action wen user requests a cancel
/// this is called from the UI thread and generally executes
@@ -779,6 +630,5 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
// this.dataContainer.Server.Cancel();
}
}
}
}

View File

@@ -8,7 +8,7 @@ using System.Xml;
using System.Collections;
using System.Diagnostics;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>
/// SqlTools Parameters, used to define what goes into starting up a Workbench Form

View File

@@ -16,7 +16,7 @@ using SFC = Microsoft.SqlServer.Management.Sdk.Sfc;
/// Moved GetConnectionName static call in a public class acessible for both
/// OEXM and OE
/// </summary>
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
internal class SharedConnectionUtil
{

View File

@@ -1,27 +0,0 @@
// //
// // Copyright (c) Microsoft. All rights reserved.
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
// using System;
// /// <summary>
// /// Defines static values for both Yukon and Shiloh
// /// </summary>
// namespace Microsoft.SqlTools.ServiceLayer.Management
// {
// public class SqlLimits
// {
// internal SqlLimits()
// {
// }
// //Define Version 9 Limits
// //Currently MAX is the same for both nVarchar and Varchar.
// public static readonly int VarcharMax = 1073741824;
// public static readonly int SysName = 128;
// //Define Pre-Version 9 Limits
// public static readonly int CommandDimensionMaxLength=3200;
// }
// }

View File

@@ -4,20 +4,20 @@
//
using System;
using System.Text;
using System.Xml;
using System.Threading;
using System.Collections;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Xml;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using System.Data.SqlClient;
using System.Collections;
using System.Reflection;
using System.Globalization;
using SMO = Microsoft.SqlServer.Management.Smo;
namespace Microsoft.SqlTools.ServiceLayer.Admin
namespace Microsoft.SqlTools.ServiceLayer.Management
{
/// <summary>
/// Internal reusable helpers

View File

@@ -77,8 +77,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
this.credentialData.CredentialIdentity = "this.textBoxIdentity.Text";
this.credentialData.SecurePassword = AdminService.BuildSecureStringFromPassword("password");
this.credentialData.SecurePasswordConfirm = AdminService.BuildSecureStringFromPassword("password");
this.credentialData.SecurePassword = CDataContainer.BuildSecureStringFromPassword("password");
this.credentialData.SecurePasswordConfirm = CDataContainer.BuildSecureStringFromPassword("password");
if (this.ServerConnection.ServerVersion.Major >= 10)
{

View File

@@ -14,6 +14,7 @@ using Microsoft.SqlServer.Management.Diagnostics;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Management;
namespace Microsoft.SqlTools.ServiceLayer.Security
{

View File

@@ -9,6 +9,7 @@ using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Admin;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Security.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.Security
@@ -95,7 +96,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Security
parameters.OwnerUri,
out connInfo);
CDataContainer dataContainer = AdminService.CreateDataContainer(connInfo, databaseExists: true);
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
Credential credential = new Credential(dataContainer);
await requestContext.SendResult(result);