如何在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.CurrentApplication_Start中不可用。

在阅读相关的帖子,特别是这一个,但我真的不明白我是否需要创建像这里描述的UnitOfWorkScope一样的东西,或者如果有一种方法可以做到这一点,因为它目前是。

那么是否有任何干净和安全的方法来安排一些任务,这些任务将使用我的UnitOfWork来更新实体?

如何在EF (DB优先)实体上实现计划任务

您的问题来自于这样一个事实,即当您的作业将运行时,它将由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任务调度器之类的东西来点击网站开始工作