Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何添加带有触发器的作业,以便在不重新启动服务器的情况下运行Quartz.NET调度程序实例?_C#_C# 4.0_Quartz.net - Fatal编程技术网

C# 如何添加带有触发器的作业,以便在不重新启动服务器的情况下运行Quartz.NET调度程序实例?

C# 如何添加带有触发器的作业,以便在不重新启动服务器的情况下运行Quartz.NET调度程序实例?,c#,c#-4.0,quartz.net,C#,C# 4.0,Quartz.net,是否可以添加带有触发器的作业,以便在不重新启动服务器的情况下运行Quartz.NET调度程序实例?您的数据存储是什么 这里有一个场景。。。有点不寻常: 您可以编写一个小型控制台应用程序(或类似程序),即“作业填充器” 您可以将其连接到从xml文件中提取作业定义,并将它们推送到ADO数据存储(sql server)中 以下是我的quartz配置以执行此操作: <quartz> <!-- This configuration is a way to have j

是否可以添加带有触发器的作业,以便在不重新启动服务器的情况下运行Quartz.NET调度程序实例?

您的数据存储是什么

这里有一个场景。。。有点不寻常:

您可以编写一个小型控制台应用程序(或类似程序),即“作业填充器”

您可以将其连接到从xml文件中提取作业定义,并将它们推送到ADO数据存储(sql server)中

以下是我的quartz配置以执行此操作:

<quartz>

    <!-- 
    This configuration is a way to have jobs defined in xml, but will get them written to the database.
    See https://stackoverflow.com/questions/21589964/ramjobstore-quartz-jobs-xml-to-adojobstore-data-move/ 
    -->


    <add key="quartz.plugin.xml.type" value="Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz" />
    <add key="quartz.plugin.xml.fileNames" value="~/Quartz_Jobs_001.xml" />
    <!-- 
    <add key="quartz.plugin.xml.ScanInterval" value="10" />
    -->

    <add key="quartz.jobStore.type" value="Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" />
    <add key="quartz.jobStore.driverDelegateType" value="Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz"/>
    <add key="quartz.jobStore.dataSource" value="default"/>
    <add key="quartz.dataSource.default.connectionString" value="Server=MyServer\MyInstance;Database=QuartzDB;Trusted_Connection=True;Application Name='quartz_config';"/>
    <add key="quartz.dataSource.default.provider" value="SqlServer-20"/>

</quartz>


ADOJobStore的一个相当健壮的实现是拥有一个自定义表来存储作业,并创建一个从IsSchedulerPlugin和IJob继承的类来自动为作业创建计划

您的配置将如下所示:

<add key="quartz.plugin.sqlquartzjobs.type" value="(JobSchedulerPlugin assembly path)" />
<add key="quartz.plugin.sqlquartzjobs.RescanCronExpression" value="0 0/5 * * * ?" /> //plugin should fire every five minutes
<add key="quartz.plugin.sqlquartzjobs.ConnectionString" value="(your connection string)" />
public class JobSchedulerPlugin : ISchedulerPlugin, IJob
{
        //Entry point for plugin, quartz server runs when it starts
        public void Initialize(string pluginName, IScheduler sched)
        {
            Name = pluginName;
            Scheduler = sched;
        }

        //Runs after Initialize()
        public void Start()
        {
                //schedule plugin as a job
            JobDataMap jobData = new JobDataMap();
            jobData["ConnectionString"] = ConnectionString;

            IJobDetail job = JobBuilder.Create(this.GetType())
                .WithDescription("Job to rescan jobs from SQL db")
                .WithIdentity(new JobKey(JobInitializationPluginJobName, JobInitializationPluginGroup))
                .UsingJobData(jobData)
                .Build();

             TriggerKey triggerKey = new TriggerKey(JobInitializationPluginJobTriggerName, JobInitializationPluginGroup);

             ITrigger trigger = TriggerBuilder.Create()
                 .WithCronSchedule(ConfigFileCronExpression)
                 .StartNow()
                 .WithDescription("trigger for sql job loader")
                 .WithIdentity(triggerKey)
                 .WithPriority(1)
                 .Build();

             Scheduler.ScheduleJob(job, trigger);
        }
}
现在JobSchedulerPlugin已经在QRTZ_触发器中输入了一个触发器,它将以最高优先级每五分钟触发一次。您可以使用它从自定义表加载作业(我们称之为QUARTZJOBS)。QUARTZJOBS可以包含诸如作业名、程序集路径、日期、状态等信息,以及任何可以帮助您高效创建触发器的信息。它还应该包含作业的cron表达式。当触发器触发时,您可以执行以下操作:

//Entry point of every job
public void Execute(IJobExecutionContext context)
{
    Scheduler = context.Scheduler;

    JobCollection jobs = LoadJobs(context.JobDetail.JobDataMap["ConnectionString"].ToString());
    JobsWithTriggers jobTriggers = CreateTriggers(jobs);
    SchedulerJob(jobTriggers);
}

//You can use ADO.NET or an ORM here to load job information from the the table
//and push it into a class. 
protected JobCollection LoadJobs(string connectionString);

//In this class you can create JobDetails and ITriggers for each job
//and push them into a custom class
protected JobsWithTriggers CreateTriggers(jobs);

//Finally here you can schedule the jobs
protected void ScheduleJobs(jobstriggers)
在上面的每个类中,您都可以添加自定义验证,以确保在状态或cron表达式发生更改时触发器得到适当处理


使用此解决方案,服务器将永远不需要重新启动。插件/作业类将扫描表并相应地执行操作。

您使用的是RAM还是ADO jobstore?在我的解决方案中,我必须连接sql server。因为所有作业计划都直接存储在sql数据库中。当您首先使用ADO jobstore时,从xml中提取作业并将其推送到数据库不是有点多余吗?为什么不直接将它们插入QUARTZJOBS表并创建一个插件,定期扫描该表并创建触发器?@Circular Reference您建议的方法正是我想要的。但要实现,我没有找到合适的文档,这就是问题所在。我们创建xml方法是因为我们的作业(需要添加)将随着时间的推移而增长。xml方式允许(仅新作业)被“附加”到数据库中。您可以直接将数据放入QuartzDB中,但我不推荐这样做。有一个API是有原因的。代码指向API,而不是后端的特定RDBMS。您还可以连接SQLServerCE进行单元测试,这是使用API而不是直接进行测试的另一个原因。@GranadCoder,您是对的,您应该始终使用API编写代码,但我的观点有点不同。您可以有一个单独的表(称为QUARTZJOBS)并将作业存储在那里。当然,您可以使用API来安排作业、创建/删除触发器等(参见我的答案)。如果你的大部分工作都发生在ADOJobStore中,那么合并商店对我来说似乎是多余的。无论如何,您都将承担使用数据库的成本;石英服务器将有效地扫描两个地方的作业和触发器。我有一个名为“PopulateNewJobs.exe”的控制台应用程序,这是唯一编码到两个数据存储的东西。主服务~只与一个数据存储(ado数据存储)通信。我同意,您不想让主quartz/服务与2个数据存储进行通信。但我们发现这个带有(仅限新)作业的xml追加有利于部署。“…从自定义表加载作业…作业名称、程序集路径、日期、状态等…”新增到Quartz.NET;我的理解是,程序集必须与Quartz.NET运行时位于同一文件夹中。但我对你的说法很感兴趣,我想实施——你能详细说明一下吗?Tx.I在Quartz.NET源代码中找不到类
JobCollection
JobsWithTriggers
——您能提供帮助吗?Tx.@InteXX正如您所看到的,只要您在项目中有一个引用,程序集就不必位于同一文件夹中。Quartz.NET通过反射加载它们。我个人将程序集路径放在QUARTZJOBS表中,并将其加载到ScheduleJobs方法中的调度器中。我的作业有单独的项目,以便更好地对它们进行分组,这对体系结构非常有用。@InteXX JobCollection和JobsWithTriggers不在Quartz.NET源代码中,它们是自定义实现。JobCollection是QUARTZJOBS表中的条目,LoadJobs方法从数据库检索该条目。CreateTriggers执行一些基本的验证。例如,我有一个IsActive列。如果设置为false,CreateTriggers方法将删除任何作业触发器(通过API)。如果它处于活动状态,并且没有触发器(或指定了其他触发器),则会将其添加到表中。@InteXX您可以使用QuartzJobs表上的IsActive列动态删除作业(请参见上面的答案)。对程序集也执行相同的操作。下次插件启动时,它会处理好它。您所说的文档缺乏更高级的功能;这通常是开源的一个问题-如果您可以扩展它,请执行以下操作:)希望这对你有帮助(如果有,请投票!)如果你还有其他问题,请随时提问。