调用作业计时存储过程
您可以通过添加一个名为JobAccess的新类来扩展数据访问层,以便调用作业计时存储过程。数据访问层中函数的作用是将业务层传递给该层的参数转换为存储过程数据库查询,并且向业务层返回结果。数据访问层的函数中的参数将镜像它们所访问的存储过程的那些参数,因为它们不对这些值执行任何业务逻辑。您将通过Microsoft Data Application Building Block的SQLHelper类访问数据库。该类包含用于简化数据访问代码的功能,从而使您的代码更为简洁,可读性更高。
要更改数据访问层以运行预定作业,请首先向现有数据访问层中添加JobAccess类,以便保持安排作业所需的函数。接下来,在JobAccess类中创建一个函数,以返回需要通过调用Job_SelectJobs_NextJobStartBefore存储过程运行的作业的DataSet。您还将需要在JobAccess类中创建一个函数以调用Job_Update_StartEnd_CalcNext存储过程,但不返回结果。
首先,将JobAccess类添加到数据访问层。然后,编辑JobAccess类以添加下列“using”语句:
using System.Data;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;
现在,让我们考察一下如何添加SelectJobsBeforeDate函数以检索需要运行的作业的列表。以下为SQLHelper的ExecuteDataset函数的签名:
public static DataSet
ExecuteDataset(
string connectionString, string spName,
params object[] parameterValues)
以下为SelectJobsBeforeDate函数,它使用ExecuteDataset来调用Job_Update_StartEnd_CalcNext存储过程,并且返回结果的DataSet:
public DataSet SelectJobsBeforeDate(DateTime beforeDate)
{
return SqlHelper.ExecuteDataset(
ConnectionInfo.connectionString,
"Job_SelectJobs_NextJobStartBefore, myparams);
new object[]{new SqlParameter("BeforeDate", beforeDate)});
}
在作业运行之后,您需要执行相应的存储过程以更新有关作业的状态信息。完成该工作的方法UpdateJob将使用SQLHelper类的ExecuteNonQuery方法。以下是它的签名:
public static int ExecuteNonQuery(
string connectionString, string spName, params object[]
parameterValues)
UpdateJob方法可以按以下方式编写:
public void UpdateJob(int JobID, DateTime dateLastJobRan)
{
string connStr = ConnectionInfo.connectionString;
string spName = "Job_Update_StartEnd_CalcNext";
SqlParameter myparam1 = new SqlParameter("JobID", JobID);
SqlParameter myparam2 = new
SqlParameter("DateLastJobRan",dateLastJobRan);
object[] myparams = {myparam1, myparam2};
SqlHelper.ExecuteNonQuery(connStr, spName, myparams);
}
JobAccess类中的UpdateJob函数应该镜像传递给它所使用的存储过程的参数。因此,UpdateJob函数具有一个JobID参数和一个dateLastJobRan参数,并且它们的数据类型与Job_Update_StartEnd_CalcNext存储过程中的参数相同。使用JobID和dateLastJobRan参数,您可以创建两个SqlParameters,将它们放到myparams对象数组中,并且使用ExecuteNonQuery函数来执行该存储过程。既然您已经创建了JobAccess类,那么您需要创建最后一个类层,以便将流程层和数据访问层连接起来。
处理预定作业
最后一个必须加以修改以便处理预定作业的层是业务逻辑层,我将其称为JobLogic。该类将对流程层和数据访问层之间的变量执行基本逻辑。
首先,使用下列语句向DataAccess层中添加JobLogic类:
using System.Data;
using ScheduledWebService.DataAccess;
其次,生成JobLogic类的GetAllActiveJobs函数,以查找所有仍然需要在当前时间或之前运行的作业,如下所示:
public DataSet GetAllActiveJobs()
{
JobAccess ja = new JobAccess();
return ja.SelectJobsBeforeDate(DateTime.Now);
}
GetAllActiveJobs函数创建JobAccess类的实例,并且用当前日期的参数值调用它的SelectJobsBeforeDate。GetAllActiveJobs选取当前日期以传递给该函数,因此您可以查明哪些作业被安排在当前时间之前运行。
最后,创建JobLogic类的UpdateJobDone函数以更新数据库,以便指示所指定的作业刚刚完成,如下所示:
public void UpdateJobDone(int JobID)
{
JobAccess ja = new JobAccess();
ja.UpdateJob(JobID, DateTime.Now);
}
该函数创建JobAccess类的实例并且调用它的UpdateJob方法。它传递JobID参数,然后使用dateLastJobRan参数的当前日期。您需要将当前日期和时间传递给UpdateJob函数,因为它是作业成功完成的时间。
小结
通过用自动完成的任务扩展ASP.NET应用程序,可以显式计划事件,而不是等待执行代码的请求。您可以利用这一功能执行多种任务——从运行复杂的计算到定期创建报告并将其发送给经理。这样的任务可以同时重用现有的逻辑和ASP.NET层中的对象,并且可以减少开发时间和提高可维护性。您还可以扩展该计划程序启动的作业,而无须更改启动它的Windows服务。
请注意,对于我在本文中讨论的内容,有许多不同的情况。例如,您可以不创建自定义的Windows服务来充当计划程序,而是使用某种像Windows任务计划程序一样简单的工具,它非常可靠,并且实现了本文中讨论的大多数功能,而无需创建自定义的Windows服务来充当计划程序。总之,.NET Framework已经大大简化了Windows服务的创建,因此即使您先前已经发现它们非常难以使用,您也应当将它们作为一种选择而重新加以考虑。类似地,Web服务是应用程序向其他应用程序公开功能的一种很好的方式,并且将继续在这一方面发挥作用。
做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。

