Quartz.net Framework Adojobstore Save job to Database

Source: Internet
Author: User
Tags datetime

The core elements of quartz.net task scheduling are scheduler, trigger and jobs, where trigger (which defines the elements of the scheduling time, what time rules are used to perform tasks), and the job is the metadata for task scheduling, scheduler is the controller that actually executes the schedule. There are two main types of jobs in Quartz.net: Stateless (stateless) and stateful (stateful). For the same trigger, a stateful job cannot be executed in parallel, and the next execution can only be triggered after the last triggered task has been executed. A stateless task generally refers to a task that can be concurrent, that is, the task is independent and does not interfere with each other. A job can be associated with multiple trigger, but a trigger can only associate one job. Some tasks require the deletion of data in the database, these tasks can not be executed concurrently, you need to use a stateless task, otherwise it will cause data chaos.

In other cases, we need to save the task to the database, especially if some of the tasks include parameters, such as cumulative tasks, if you can save to the database, even if the intermediate power outage or the program abnormal restart, the results of the intermediate calculation will not be lost, you can work from the result of the breakpoint (first restore Task) Here's how to use Adojobstore to save tasks to a SQL Server database.

Create a new Qrtz_ database on the database and execute the SQL table script in advance:

1 Recoveryjob

is a stateless task with the following code:

Using System;
Using System.Collections.Specialized;
Using System.Threading;
Using Common.logging;
Using Quartz;
Using Quartz.impl;
Using Quartz.job;
Using System.Windows.Forms;
Namespace Quartzdemo
{
<summary>
Non-stateful recoverable tasks
</summary>
public class Recoveryjob:ijob
{

Private Const string count = "Count";
public virtual void Execute (Ijobexecutioncontext context)
{

Jobkey Jobkey = context. Jobdetail.key;
if (IsOpen ("Frmconsole"))
{
Try
{
Get the current Form1 instance
__instance = (frmconsole) application.openforms["Frmconsole"];
If the mission is a recovery mission,
if (context. recovering)
{
__instance. SetInfo (String. Format ("{0} recovering at {1}", Jobkey, DateTime.Now.ToString ("R")));
}
Else
{
__instance. SetInfo (String. Format ("{0} starting at {1}", Jobkey, DateTime.Now.ToString ("R")));
}

Jobdatamap data = context. Jobdetail.jobdatamap;
int count;
if (data. ContainsKey (Count))
{
Whether you can recover from the database, if you save the job and other information, the program runs a sudden terminal (can be interrupted when debugging, rather than close the form to simulate)
Count = data. GetInt (Count);
}
Else
{
Count = 0;
}
count++;
Data. Put (count, count);

__instance. SetInfo (String. Format ("{0} Count #{1}", Jobkey, Count));
}
catch (Exception ex)
{
Console.WriteLine (ex. message);
}
}
}


private static Frmconsole __instance = null;

<summary>
Determine if a form is open
</summary>
<param name= "AppName" ></param>
<returns></returns>
private bool IsOpen (string appName)
{
FormCollection collection = Application.openforms;
foreach (Form form in collection)
{
if (form. Name = = appName)
{
return true;
}
}
return false;
}

}
}

2 Recoverystatefuljob

is a stateful task, and no state is the difference between the task class with [Persistjobdataafterexecution] callout task is stateful, stateful tasks do not allow concurrent execution, also need to callout [ Disallowconcurrentexecution], the code is as follows:

Using System;
Using System.Collections.Specialized;
Using System.Threading;
Using Common.logging;
Using Quartz;
Using Quartz.impl;
Using Quartz.job;
Using System.Windows.Forms;
Namespace Quartzdemo
{
<summary>
Using this [persistjobdataafterexecution] annotation task is stateful,
Stateful tasks do not allow concurrent execution [disallowconcurrentexecution]
</summary>
[Persistjobdataafterexecution]
[Disallowconcurrentexecution]
public class Recoverystatefuljob:recoveryjob
{

}
}

3 Adojobstoreexample

With properties["quartz.dataSource.default.connectionString"] = "server= (local);D atabase=qrtz_; Trusted_connection=true; "; Define the connection information for the database, and the program will automatically save the task to the database when it runs:

Using System;
Using System.Collections.Specialized;
Using System.Threading;
Using Common.logging;
Using Quartz;
Using Quartz.impl;
Using Quartz.job;
Using System.Windows.Forms;
Namespace Quartzdemo
{
<summary>
Examples of adojobstore usage
</summary>
public class Adojobstoreexample
{
public virtual void Run (bool inclearjobs, BOOL inschedulejobs)
{
NameValueCollection properties = new NameValueCollection ();

properties["quartz.scheduler.instanceName"] = "Testscheduler";
properties["quartz.scheduler.instanceId"] = "Instance_one";
properties["Quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, quartz";
properties["Quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["Quartz.jobStore.misfireThreshold"] = "60000";
properties["Quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, quartz";
properties["quartz.jobStore.useProperties"] = "false";
properties["Quartz.jobStore.dataSource"] = "Default";
properties["Quartz.jobStore.tablePrefix"] = "qrtz_";
properties["quartz.jobStore.clustered"] = "true";
Sqlite
properties["Quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, quartz";
properties["Quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, quartz";
Database connection string
properties["quartz.dataSource.default.connectionString"] = "server= (local);D atabase=qrtz_; Trusted_connection=true; ";
properties["Quartz.dataSource.default.provider"] = "SqlServer-20";

A reference to a scheduler must
Ischedulerfactory SF = new Stdschedulerfactory (properties);
IScheduler sched = sf. Getscheduler ();

Whether bool B is restored = false;
if (inclearjobs)
{
Console.WriteLine ("* * * Deleting existing jobs/triggers");
Sched. Clear ();
}


if (inschedulejobs)
{

String schedid = Sched. Schedulerinstanceid;

int count = 1;

Define a stateless task
Ijobdetail job = jobbuilder.create<recoveryjob> ()
. Withidentity ("recoveryjob_" + count, Schedid)
. Requestrecovery ()//recovery
. Build ();


Isimpletrigger trigger = (Isimpletrigger) triggerbuilder.create ()
. Withidentity ("Triger_" + count, Schedid)
. StartAt (Datebuilder.futuredate (1, Intervalunit.second))
. Withsimpleschedule (x => x.withrepeatcount (20). Withinterval (Timespan.fromseconds (3)))
. Build ();
Use this to view a defined trigger trigger rule
Log.infoformat ("{0} would run at: {1} and repeat: {2} times, every {3} seconds")
Job. Key, Trigger. GETNEXTFIRETIMEUTC (),
Trigger. RepeatCount,
Trigger. Repeatinterval.totalseconds);
Try
{
Bind fails if the database already has a job and trigger with the same name
Sched. Schedulejob (Job, trigger);
}
Catch
{
B is recovery = true;
}
count++;

Define a stateful task ***********************************************************
Job = jobbuilder.create<recoverystatefuljob> ()
. Withidentity ("statefuljob_" + count, Schedid)
. Requestrecovery ()//recovery
. Build ();

Trigger = (Isimpletrigger) triggerbuilder.create ()
. Withidentity ("Triger_" + count, Schedid)
. StartAt (Datebuilder.futuredate (1, Intervalunit.second))
. Withsimpleschedule (x => x.withrepeatcount (20). Withinterval (Timespan.fromseconds (3)))
. Build ();

Try
{
Sched. Schedulejob (Job, trigger);
}
Catch
{
B is recovery = true;
}



}

Start
Sched. Start ();
Sched. Shutdown ();

}

public string Name
{
get {return GetType (). Name; }
}

public void Run ()
{
bool Clearjobs = true;
Clearjobs = false;
bool Schedulejobs = true;
adojobstoreexample example = new Adojobstoreexample ();
Example. Run (Clearjobs, schedulejobs);
}
}
}


You can see that there is a state of the count of 1 each time, and no state of each execution will lose the cumulative number (new instance), interrupt the program, view the Database Qrtz_job_details table, you can see that there is a persistent task:

After the program is interrupted (the form is not closed while debugging, the debugging is interrupted, the simulation is turned off), and then rerun, you can see the following interface:


Quartz.net-adojobstore Job Store

Quartz provides two basic types of job storage. The first type is called Ramjobstore, which uses the usual memory to persist scheduler information. This type of job storage is easiest to configure, construct, and run. Quartz.net default is to use Ramjobstore. For many applications, this kind of job storage is sufficient.

However, because the scheduler information is stored in memory, all scheduling information is lost when the application stops running. If you need to persist scheduling information between reboots, you will need a second type of job store. To correct this problem, Quartz.net provides adojobstore. As the name suggests, the Operation warehouse through ADO. NET put all the data in the database. The cost of data persistence is performance degradation and increased complexity. It saves all data through ado.net to the database. Its configuration is slightly more complex than Ramjobstore, and it is not as fast. But the performance flaw is not very poor, especially if you are indexing on the primary key of a database table.
Adojobstore can work on almost any database, and it uses Oracle, MySQL, MS SQLServer2000, HSQLDB, Postresql, and DB2 extensively. To use Adojobstore, you first have to create a set of database tables that quartz use, and you can find SQL scripts that create the library tables Quartz database\tables. If you don't find a script for your database type, then find an existing one that you need to modify to be your database. One thing to note is that all Quartz library table names are prefixed by qrtz_ (for example, table "Qrtz_triggers" and "Qrtz_job_detail"). In fact, you can set the prefix to any prefix you want, as long as you tell adojobstore what the prefix is (configured in your Quartz property file). With multiple scheduler instances in a database, it is useful to configure different prefixes to create multiple sets of library tables.

The SQL Server code connection looks like this:

Adojobstorerunner
NameValueCollection properties = new NameValueCollection ();
properties["quartz.scheduler.instanceName"] = "Testscheduler";
properties["quartz.scheduler.instanceId"] = "Instance_one";
properties["Quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, quartz";
properties["Quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["Quartz.jobStore.misfireThreshold"] = "60000";
properties["Quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, quartz";
properties["Quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.StdAdoDelegate, quartz";
properties["quartz.jobStore.useProperties"] = "false";
properties["Quartz.jobStore.dataSource"] = "Default";
properties["Quartz.jobStore.tablePrefix"] = "qrtz_";
properties["quartz.jobStore.clustered"] = "true";
If running MS SQL Server we need this
properties["Quartz.jobStore.selectWithLockSQL"] = "SELECT * FROM {0}locks UPDLOCK WHERE lock_name = @lockName";
properties["quartz.dataSource.default.connectionString"] = "Server=local;database=quartz;user id=<span style=" Font-family:arial, Helvetica, Sans-serif; " >sa</span><span style= "font-family:arial, Helvetica, Sans-serif;" >;p wd=sa;pooling=false; "; </span>
properties["Quartz.dataSource.default.provider"] = "SqlServer-20";


Ischedulerfactory SF = new Stdschedulerfactory (properties);
IScheduler sched = sf. Getscheduler ();
String schedid = Sched. Schedulerinstanceid;
int count = 1;
for (int i = 0; i < i++)
{

Homework
Ijobdetail job = Jobbuilder
. Create<job1> ()
. Withidentity ("Compute job" + i.tostring (), "Group 1")
. Requestrecovery ()//Ask Scheduler to re-execute this job if it is in progress then scheduler down ...
. Build ();

DateTimeOffset runTime = datebuilder.evenminutedate (Datetimeoffset.utcnow);

Itrigger trigger = Triggerbuilder.create ()
. Withidentity ("Trigger" + i.tostring (), "group1")
. StartAt (RunTime)
. Build ();
associating tasks and Triggers
Sched. Schedulejob (Job, trigger);

}
Start Task
Sched. Start ();


<configuration>
<configSections>
<section name= "Quartz" type= "System.Configuration.NameValueSectionHandler, System, version=1.0.5000.0,culture= Neutral, publickeytoken=b77a5c561934e089 "/>
</configSections>
<quartz>
<add key= "Quartz.scheduler.instanceName" value= "Exampledefaultquartzscheduler"/>

<add key= "Quartz.threadPool.type" value= "Quartz.Simpl.SimpleThreadPool, quartz"/>
<add key= "Quartz.threadPool.threadCount" value= "ten"/>
<add key= "quartz.threadPool.threadPriority" value= "2"/>

<add key= "Quartz.jobStore.misfireThreshold" value= "60000"/>
<add key= "Quartz.jobStore.type" value= "Quartz.Simpl.RAMJobStore, quartz"/>
</quartz>
</configuration>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.