mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-17 01:25:40 -05:00
308 lines
9.6 KiB
C#
308 lines
9.6 KiB
C#
//
|
|
// Copyright (c) Microsoft. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
|
using Microsoft.SqlServer.Management.Smo.Agent;
|
|
using Microsoft.SqlTools.ServiceLayer.Management;
|
|
|
|
namespace Microsoft.SqlTools.ServiceLayer.Agent
|
|
{
|
|
internal class JobSchedulesData
|
|
{
|
|
#region data members
|
|
|
|
// Typed List of job schedules (unshared)
|
|
private List<JobScheduleData> jobSchedules = new List<JobScheduleData>();
|
|
private List<JobScheduleData> deletedJobSchedues = new List<JobScheduleData>();
|
|
|
|
private JobData parent;
|
|
private CDataContainer context;
|
|
private bool isReadOnly;
|
|
private bool allowEnableDisable;
|
|
|
|
#endregion
|
|
|
|
#region construction
|
|
public JobSchedulesData(CDataContainer context, JobData parent)
|
|
{
|
|
if (context == null)
|
|
{
|
|
throw new ArgumentNullException("context");
|
|
}
|
|
|
|
if (parent == null)
|
|
{
|
|
throw new ArgumentNullException("parent");
|
|
}
|
|
|
|
this.context = context;
|
|
this.parent = parent;
|
|
|
|
this.isReadOnly = parent.IsReadOnly;
|
|
this.allowEnableDisable = parent.AllowEnableDisable;
|
|
|
|
// if we're creating a new job
|
|
if (this.parent.Mode != JobData.ActionMode.Edit)
|
|
{
|
|
this.SetDefaults();
|
|
}
|
|
else
|
|
{
|
|
// load the schedule data from server to local copy
|
|
this.LoadData();
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region public methods/properties
|
|
|
|
/// <summary>
|
|
/// List of JobScheduleData - in memory copy
|
|
/// </summary>
|
|
public List<JobScheduleData> Schedules
|
|
{
|
|
get
|
|
{
|
|
return this.jobSchedules;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// List of removed schedules - in memory copy
|
|
/// </summary>
|
|
public List<JobScheduleData> RemovedSchedules
|
|
{
|
|
get
|
|
{
|
|
return this.deletedJobSchedues;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add a schedule to JobScheduleData list - this does not apply changes on server
|
|
/// </summary>
|
|
/// <param name="schedule"></param>
|
|
public void AddSchedule(JobScheduleData schedule)
|
|
{
|
|
if (schedule == null)
|
|
{
|
|
throw new ArgumentNullException("schedule");
|
|
}
|
|
|
|
this.jobSchedules.Add(schedule);
|
|
|
|
// check to see if it has been previously removed, if so delete it from the
|
|
// removed schedules list
|
|
for (int i = deletedJobSchedues.Count - 1; i >= 0; i--)
|
|
{
|
|
JobScheduleData removedSchedule = this.deletedJobSchedues[i] as JobScheduleData;
|
|
if (removedSchedule.ID == schedule.ID)
|
|
{
|
|
this.deletedJobSchedues.RemoveAt(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// delete a schedule from JobScheduleData list - this does not apply changes on server
|
|
/// </summary>
|
|
/// <param name="schedule"></param>
|
|
public void DeleteSchedule(JobScheduleData schedule)
|
|
{
|
|
if (schedule == null)
|
|
{
|
|
throw new ArgumentNullException("schedule");
|
|
}
|
|
if (this.jobSchedules.Contains(schedule))
|
|
{
|
|
this.jobSchedules.Remove(schedule);
|
|
// if it exists on the server then mark it for deletion later. Otherwise just discard the schedule.
|
|
if (schedule.Created)
|
|
{
|
|
this.deletedJobSchedues.Add(schedule);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsReadOnly
|
|
{
|
|
get { return isReadOnly; }
|
|
}
|
|
|
|
public bool AllowEnableDisable
|
|
{
|
|
get { return this.allowEnableDisable; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region data loading
|
|
private void LoadData()
|
|
{
|
|
Job job = this.Job;
|
|
// load the data
|
|
if (job != null)
|
|
{
|
|
JobScheduleCollection schedules = job.JobSchedules;
|
|
|
|
for (int i = 0; i < schedules.Count; i++)
|
|
{
|
|
this.jobSchedules.Add(new JobScheduleData(schedules[i], this.IsReadOnly, this.AllowEnableDisable));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetDefaults();
|
|
}
|
|
}
|
|
private void SetDefaults()
|
|
{
|
|
this.jobSchedules.Clear();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region events
|
|
|
|
#endregion
|
|
|
|
#region private helpers
|
|
private Job Job
|
|
{
|
|
get
|
|
{
|
|
// try and do the lookup at the parent level
|
|
Job job = null;
|
|
if (this.parent != null)
|
|
{
|
|
job = parent.Job;
|
|
}
|
|
else if (this.context != null)
|
|
{
|
|
STParameters parameters = new STParameters(this.context.Document);
|
|
string urn = String.Empty;
|
|
parameters.GetParam("urn", ref urn);
|
|
|
|
job = this.context.Server.GetSmoObject(new Urn(urn)) as Job;
|
|
}
|
|
return job;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region saving
|
|
/// <summary>
|
|
/// Save changes to the job schedules - this applies changes to server
|
|
/// </summary>
|
|
/// <param name="job">owner job</param>
|
|
/// <returns>true if any changes were commited</returns>
|
|
public bool ApplyChanges(Job job)
|
|
{
|
|
bool changesMade = false;
|
|
if (!this.IsReadOnly)
|
|
{
|
|
// delete any deleted schedules;
|
|
foreach (JobScheduleData schedule in this.deletedJobSchedues)
|
|
{
|
|
if (!this.IsSharedSchedule(job.Parent as JobServer, schedule))
|
|
{
|
|
// non-shared
|
|
if (schedule.Created)
|
|
{
|
|
schedule.SetJob(job);
|
|
schedule.Delete();
|
|
changesMade = true;
|
|
}
|
|
}
|
|
else if (null != job.JobSchedules.ItemById(schedule.ID))
|
|
{
|
|
// shared
|
|
// Remove the selected schedule from the job. If no other jobs use the schedule, the schedule is deleted from the database.
|
|
// This is now the default behavior of RemoveSharedSchedule thus we do not need an extra parameter (false) with it.
|
|
job.RemoveSharedSchedule(schedule.ID);
|
|
changesMade = true;
|
|
}
|
|
}
|
|
|
|
// clear the deleted Job ScheduleList
|
|
this.deletedJobSchedues.Clear();
|
|
|
|
// update the remaining schedules
|
|
foreach (JobScheduleData schedule in this.jobSchedules)
|
|
{
|
|
if (!this.IsSharedSchedule(job.Parent as JobServer, schedule))
|
|
{
|
|
// non-shared
|
|
schedule.SetJob(job);
|
|
if (schedule.ApplyChanges())
|
|
{
|
|
changesMade = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// create and attach if the the schedule is not shared
|
|
if (!schedule.Created)
|
|
{
|
|
schedule.SetJob(job);
|
|
changesMade = true;
|
|
}
|
|
else
|
|
{
|
|
job.AddSharedSchedule(schedule.ID);
|
|
}
|
|
if (schedule.ApplyChanges())
|
|
{
|
|
changesMade = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (this.AllowEnableDisable)
|
|
{
|
|
// if the schedules are readonly give them an opportunity to update themselves
|
|
foreach (JobScheduleData schedule in this.jobSchedules)
|
|
{
|
|
if (schedule.ApplyChanges())
|
|
{
|
|
changesMade = true;
|
|
}
|
|
}
|
|
}
|
|
return changesMade;
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// check if given schedule data is shared schedule or not
|
|
/// </summary>
|
|
/// <param name="js"></param>
|
|
/// <param name="jobScheduleData"></param>
|
|
/// <returns></returns>
|
|
private bool IsSharedSchedule(JobServer js, JobScheduleData jobScheduleData)
|
|
{
|
|
if (js == null)
|
|
{
|
|
throw new ArgumentNullException("js");
|
|
}
|
|
|
|
SqlServer.Management.Smo.Server srv = js.Parent as SqlServer.Management.Smo.Server;
|
|
|
|
if ((srv == null) || (srv.Information.Version.Major < 9))
|
|
{
|
|
// Shared Schedules not supported prior Yukon
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// with Yukon all schedules are now shared
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|