2015-06-02 33 views
0

我對Asp.net挺新的,有一個網站使用Entity Framework。每天晚上,我需要在我的Person實體上做一些工作。 因此我安裝Quartz.Net等試圖用這種方式在Global.asax如何在EF(DB優先)實體上實現計劃任務?

<%@ 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但我真的不明白,如果我確實需要像UnitOfWorkScopedescribed here創造的東西,或者有可能是一個辦法做到這一點,因爲它是目前。

那麼是否有任何干淨和安全的方式來安排一些任務,這將使用我的UnitOfWork以更新實體?

非常感謝。

回答

2

你的問題來自於這樣的事實:當你的工作將運行時,它將不會由http請求(即使該工作在ASP網站中)而由石英調度器調用。

所以HttpContext.Current將很可能爲空。

請記住,使用Quartz時,你應該把它看作是一個完全平行的過程到你的網站,幾乎就像一個單獨的服務。

如果需要「的說法」傳遞給你的工作,你可以使用作業數據映射

JobDataMap dataMap = jobContext.JobDetail.JobDataMap; 

(在這裏看到更多的信息:http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/more-about-jobs.html

如果您需要訪問你的工作,創建一個工作密鑰時使用相同的密鑰和組(WithIdentity

請注意,建議實體上下文僅在您需要的操作時間內存活,因此您c可能只是在工作開始時實例化一個新的上下文,並在最後處理它。

+0

感謝您的回覆!這是我第一次做這種事情,所以它真的有幫助。我看了一下你所關聯的教程,但我不明白在這種情況下可以用'JobDataMap'完成什麼。我理解它是如何工作的,但是爲了能夠使用我的實體,我可以通過什麼樣的論證來工作? –

+1

jobdatamap允許您在爲未來運行作業創建作業期間傳遞參數(字符串,數字和對象)。在你的情況下,你不需要傳遞參數,只需要在作業開始時使用'using(_dbContext = new MyEntities())'執行部分 –

+0

這很好,我簡直不敢相信我沒有想過直接使用'new MyEntities()'。非常感謝(爲了您對Quartz調度程序保持活躍狀態​​的評論),您讓我的一天! –

1

問題是您沒有在Web請求中執行作業。如在Web請求開始時,您會檢查未完成的工作,如果需要請執行工作,請求結束。如果沒有Web請求,則沒有上下文 - 因爲上下文用於Web請求的生命週期,並可通過請求線程訪問。

您將遇到的另一個問題是,如果沒有任何活動,則使用默認設置的應用程序池可能會結束。所以你需要一種方法來保持它的活力。

另一種方法是使用類似win任務調度程序的命令來啓動網站以啓動工作。

+0

感謝Plebsori的解釋!我不得不承認,我對網絡請求並不十分熟悉,但你幫助我瞭解了發生的事情。我並不是特別注意應用程序池,但我會研究它。那麼從你的角度來看什麼是最好的;找到一種方法來保持它活着或用任務調度程序觸發它? –

+0

根據經驗,我可以告訴Quartz Scheduler保持應用程序池沒有任何特定的配置,所以你不必擔心^^ –

+0

我見過這個問題的各種解決方案。沒有一個是偉大的,都有利弊。我建議快速谷歌爲'asp.net背景工作'或類似 – Plebsori

相關問題