簡體   English   中英

asp.net core dbcontext 在計時器結束時被處理

[英]asp.net core dbcontext is disposed when timer elapsed

我的 asp.net 應用程序有問題。

我的應用程序應該每天抓取一個網站一次。

我正在嘗試使用計時器觸發一個方法,我正在嘗試處理的這個方法需要我的 dbcontext 來保存新數據。

如果我運行我的應用程序並轉到根據請求調用此方法的頁面,我的方法工作正常,但是當計時器嘗試使用它時,我的 dbcontext 會被處理。

我的問題是.. 我如何配置我的 asp.net 應用程序,以便我可以在后台重用我的 dbcontext 而不依賴於來自 Web 瀏覽器的請求?

這是一些代碼:

啟動文件

public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<FundContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("FundContext")));

        services.AddTransient<IFundDataService, FundDataService>();

        services.AddMvc();            
    }

FundContext.cs

    public class FundContext : DbContext, IFundContext
    {
    public FundContext(DbContextOptions<FundContext> options)
        : base(options)
    {

    }

    public DbSet<Fund> Funds { get; set; }
}

FundsModel.cshtml.cs

public class FundsModel : PageModel
{
    private IFundDataService fundDataService;

    public FundsModel(IFundDataService fundDataService)
    {
        this.fundDataService = fundDataService;            
    }

    public void OnGet()
    {

    }

    public List<Fund> TodaysFundList { get { return fundDataService.TodaysFundList; } }

    public List<Fund> YesterdaysFundList { get { return fundDataService.YesterdaysFundList; } }
}

基金數據服務.cs

public class FundDataService : Controller, IFundDataService
{
    private FundContext fundContext;
    private List<Fund> todaysFundList;
    private List<Fund> yesterdaysFundList;

    private static Timer timer;

    public FundDataService(FundContext fundContext)
    {
        this.fundContext = fundContext;

        GetFundFromWebAndSavetoDB();
        PopulateFundLists();

        InitializeTimer();
    }

    public List<Fund> TodaysFundList { get { return todaysFundList; } }

    public List<Fund> YesterdaysFundList{ get { return yesterdaysFundList; } }

    private void InitializeTimer()
    {
        DateTime timeNow = DateTime.Now;
        DateTime scheduledTime = new DateTime(timeNow.Year, timeNow.Month, timeNow.Day, 00, 01, 00);

        if(timeNow > scheduledTime)
        {
            scheduledTime = scheduledTime.AddDays(1);
        }

        double tickTime = 10000;/*(double)(scheduledTime - DateTime.Now).TotalMilliseconds;*/
        timer = new Timer(tickTime);
        timer.Elapsed += Timer_Elapsed;
        timer.Start();
    }

    private void Timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        timer.Stop();

        GetFundFromWebAndSavetoDB();
        PopulateFundLists();

        InitializeTimer();
    }

    private void PopulateFundLists()
    {
        todaysFundList = new List<Fund>();
        yesterdaysFundList = new List<Fund>();

        foreach (var fund in fundContext.Funds)
        {
            if(fund.DateAddedToDB == DateTime.Now.Date)
            {
                todaysFundList.Add(new Fund
                {
                    ID = fund.ID,
                    Name = fund.Name,
                    RateLastDay = fund.RateLastDay,
                    RateThisYear = fund.RateThisYear,
                    LastUpdate = fund.LastUpdate,
                    DateAddedToDB = fund.DateAddedToDB
                });
            }
            if (fund.DateAddedToDB == DateTime.Now.Date.AddDays(-1))
            {
                yesterdaysFundList.Add(new Fund
                {
                    ID = fund.ID,
                    Name = fund.Name,
                    RateLastDay = fund.RateLastDay,
                    RateThisYear = fund.RateThisYear,
                    LastUpdate = fund.LastUpdate,
                    DateAddedToDB = fund.DateAddedToDB
                });
            }               
        }

        todaysFundList.Sort(delegate (Fund a, Fund b)
        {
            return b.RateThisYear.CompareTo(a.RateThisYear);
        });

        yesterdaysFundList.Sort(delegate (Fund a, Fund b)
        {
            return b.RateThisYear.CompareTo(a.RateThisYear);
        });
    }

    private void GetFundFromWebAndSavetoDB()
    {
        var rawData = WebScrapingService.Instance.WebScrapeSiteAndReturnCollection(
            "url"
            , "//tbody/tr");            

        foreach (var fund in rawData)
        {
            decimal rateLastDay;
            bool rateLastDayOK = decimal.TryParse(fund.ChildNodes[5].InnerText, out rateLastDay);

            decimal rateThisYear;
            bool rateThisYearOK = decimal.TryParse(fund.ChildNodes[11].InnerText, out rateThisYear);

            var newFund = new Fund
            {
                Name = fund.ChildNodes[3].InnerText,
                RateLastDay = rateLastDay,
                RateThisYear = rateThisYear,
                LastUpdate = Convert.ToDateTime(fund.ChildNodes[21].InnerText),
                DateAddedToDB = DateTime.Now.Date
            };

            var NumberOfFundsAddedToday = (from x in fundContext.Funds where x.DateAddedToDB == DateTime.Now.Date select x).Count();

            if(NumberOfFundsAddedToday < 5)
            {
                fundContext.Funds.Add(newFund);
                fundContext.SaveChanges();
            }                
        }            
    }
}

我認為最好的形式給出的實例化上下文中的每個ellapsed時間,注入DbContextOptions<FundContext>代替FundContextFundDataService構造和更好的控制做一個使用/新:

private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
...

    using(var context = new FundContext(_options)){
        GetFundFromWebAndSavetoDB(context);
        PopulateFundLists(context);  
    }

...
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM