如何在EF (DB优先)实体上实现计划任务
本文关键字:实体 实现 计划 任务 优先 EF DB | 更新日期: 2023-09-27 17:52:42
我是Asp.net
的新手,有一个使用Entity Framework
的网站。每天晚上,我都需要在我的Person
实体上做一些工作。因此,我安装了Quartz.Net
,并试图在Global.asax
中这样使用它:
<%@ Application Language="C#" %>
<%@ Import Namespace="Quartz" %>
<%@ Import Namespace="Quartz.Impl" %>
<script runat="server">
private IScheduler Scheduler { get; set; }
void Application_Start(object sender, EventArgs e)
{
Scheduler = StdSchedulerFactory.GetDefaultScheduler();
Scheduler.Start();
IJobDetail dailyReset = JobBuilder.Create<ApplicationJobs.DailyReset>()
.WithIdentity("dailyReset", "group1")
.Build();
ITrigger dailyResetTrigger = TriggerBuilder.Create()
.WithIdentity("dailyResetTrigger", "group1")
.StartAt(DateBuilder.DateOf(3, 0, 0))
.WithSimpleSchedule(x => x
.WithIntervalInHours(24)
.RepeatForever())
.Build()
Scheduler.ScheduleJob(dailyReset, dailyResetTrigger);
}
</script>
然后是ApplicationJobs类:
public class ApplicationJobs : System.Web.HttpApplication
{
public class DailyReset : IJob
{
public void Execute(IJobExecutionContext context)
{
using (var uow = new UnitOfWork())
{
foreach (Person person in uof.Context.Persons)
{
//do something
}
}
}
}
}
最后是UnitOfWork:
public class UnitOfWork : IDisposable
{
private const string _httpContextKey = "_unitOfWork";
private MyEntities _dbContext;
public static UnitOfWork Current
{
get { return (UnitOfWork)HttpContext.Current.Items[_httpContextKey]; }
}
public UnitOfWork()
{
HttpContext.Current.Items[_httpContextKey] = this;
}
public MyEntities Context
{
get
{
if (_dbContext == null)
_dbContext = new MyEntities();
return _dbContext;
}
}
}
但是using (var uow = new UnitOfWork())
不工作,因为HttpContext.Current.Items[_httpContextKey] = this;
在ow的构造函数;我读到HttpContext.Current
在Application_Start
中不可用。
在阅读相关的帖子,特别是这一个,但我真的不明白我是否需要创建像这里描述的UnitOfWorkScope
一样的东西,或者如果有一种方法可以做到这一点,因为它目前是。
那么是否有任何干净和安全的方法来安排一些任务,这些任务将使用我的UnitOfWork
来更新实体?
您的问题来自于这样一个事实,即当您的作业将运行时,它将由quartz调度器调用,而不是从http请求(即使作业在ASP网站中)。
所以HttpContext。Current很可能为空
请记住,当你使用Quartz时,你应该把它看作是一个完全并行的过程,你的网站,几乎像一个单独的服务。
如果需要将"argument"传递给作业,可以使用作业数据映射
JobDataMap dataMap = jobContext.JobDetail.JobDataMap;
(查看更多信息:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-jobs.html)
如果您需要访问您的作业,只需在创建jobkey时使用相同的键和组(您在WithIdentity
中使用的键和组)。请注意,建议实体上下文仅在需要它的操作时处于活动状态,因此您可以在作业开始时实例化一个新上下文,并在结束时将其处置。
问题是您没有在web请求中执行作业。例如,web请求开始,您检查未完成的工作,如果需要,执行工作,请求结束。没有web请求就没有上下文——因为上下文在web请求的生命周期内存在,并且可以通过请求线程访问。
你会遇到的另一个问题是app-pool,使用默认设置,可能会在没有活动时结束。所以你需要一种方法来保持它的活力。
另一种方法是使用win任务调度器之类的东西来点击网站开始工作