如何在EF(数据库优先)实体上实现计划任务?

时间:2015-06-02 08:04:41

标签: c# asp.net entity-framework scheduled-tasks

我是Asp.net的新手,并且使用Entity Framework建立了一个网站。每天晚上,我都需要在我的Person实体上做一些工作。 因此我安装了Quartz.Net et尝试在Global.asax中使用它{/ p>

<%@ 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())因uow的构造函数中的HttpContext.Current.Items[_httpContextKey] = this;而无效;我读到HttpContext.Current中没有Application_Start

在阅读相关帖子中,特别是this one,但我真的不明白我是否需要创建类似UnitOfWorkScope described here的内容,或者是否有办法实现就像现在一样。

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

非常感谢。

2 个答案:

答案 0 :(得分:2)

你的问题来自这样一个事实:当你的工作运行时,它将由石英计划器调用,而不是来自http请求(即使作业在ASP网站中)。

所以HttpContext.Current很可能是null。

在使用Quartz时请记住,您认为它是一个完全平行的网站流程,几乎就像一个单独的服务。

如果你需要通过&#34;论证&#34;为了您的工作,您可以使用工作数据地图

JobDataMap dataMap = jobContext.JobDetail.JobDataMap;

(有关详情,请参阅此处:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-jobs.html

如果您需要访问作业,只需在创建jobkey时使用相同的键和组(您在 WithIdentity中使用的那个

请注意,建议实体上下文仅在您需要的操作时保持活动状态,因此您可能只需在作业开始时实例化新上下文并在最后处置它。

答案 1 :(得分:1)

问题是您没有在Web请求中执行作业。在Web请求启动时,您检查未完成的工作,如果需要,请执行工作,请求结束。没有Web请求,您就没有上下文 - 因为上下文是Web请求的生命周期,可以通过请求线程访问。

您将要遇到的另一个问题是,如果没有活动,使用默认设置的应用池可能会结束。所以你需要一种方法让它保持活力。

另一种方法是使用win task scheduler之类的东西来点击网站开始工作。