10,729
edits
Line 119: | Line 119: | ||
When you fetch data but don't use the result, you can encounter the exception <code>System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first</code>. To avoid this problem, make sure that all fetch results are used. | When you fetch data but don't use the result, you can encounter the exception <code>System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first</code>. To avoid this problem, make sure that all fetch results are used. | ||
== Example: Schedule a workflow == | |||
One of the possible use cases is to schedule a job with a delay. For example, you have a trigger that executes when a new account record is created. You don't want to perform the follow-up action immediately but after a delay. | |||
Use the following sample to schedule the job. | |||
<syntaxhighlight lang="js"> | |||
protected void ScheduleJob() | |||
{ | |||
// schedule job | |||
var processService = this.Context.GetService(typeof(IPluginProcessService)) as IPluginProcessService; | |||
if (processService != null) | |||
{ | |||
var job = new PluginScheduleJob(); | |||
job.Name = $"Scheduled Test Job"; | |||
job.RegardingObjectId = new XRMServer.Data.EntityReference(Guid.NewGuid(), "account"); | |||
job.TriggerAt = DateTime.Now.AddMinutes(1); | |||
job.TypeName = typeof(Fieldiu.Plugins.accountP).FullName; | |||
job.Data = this.SerializeData(data); | |||
processService.ScheduleJob(job); | |||
} | |||
} | |||
</syntaxhighlight> | |||
To send data for the job, use the following line: | |||
<syntaxhighlight lang="js"> | |||
job.Data = this.SerializeData(data); | |||
</syntaxhighlight> | |||
In the scheduled job, this is how you can retrieve the data as the input parameter: | |||
<syntaxhighlight lang="js"> | |||
object userData; | |||
if (!this.Context.InputParameters.TryGetValue(PluginInputParameterName.UserData, out userData)) | |||
return PluginResult.Canceled; | |||
var mySerializedData = (string)userData; | |||
</syntaxhighlight> | |||
A similar solution can also be useful for long-running jobs. In that case, replace <code>TriggerAt</code> with <code>job.Recurrence = processService.GetRecurrence(0, 1);</code>. Keep in mind that long-running jobs (e.g., when generating some statistics) must be stopped after 5 minutes (or they will be aborted by the system). Return <code>PluginResult.InProgress</code>. Store the current state into data: <code>this.Context.InputParameters[PluginInputParameterName.UserData] = this.SerializeBatchData(result, entity);</code>. When everything is complete, return <code>PluginResult.Succeeded;</code> | |||