具有DbContext的服务器端计时器 [英] Server side timer with DbContext

查看:127
本文介绍了具有DbContext的服务器端计时器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让计时器在每60秒运行一次method()的服务器上运行

I want to make a timer running in the server that runs a method() every 60 seconds

现在我已经完成了-使用以下代码

now i have done -sort of- that using the code below

public class Alarm
{

    public Alarm(AppDbContext _db)
    {
        db = _db;
    }


    private static Timer aTimer;
    private AppDbContext db;

    public void StartTimerEvent()
    {
        // Create a timer and set a 60 second interval.
        aTimer = new Timer();
        aTimer.Interval = 60000;

        // Hook up the Elapsed event for the timer. 
        aTimer.Elapsed += (source, e) => CheckDBEvents(source, e);
        // Have the timer fire repeated events (true is the default)
        aTimer.AutoReset = true;
        // Start the timer
        aTimer.Enabled = true;

    }


    private void CheckDBEvents(Object source, ElapsedEventArgs e)
    {

        //get data from db with matching queries
        List<Grocery> DataList = db.Grocery.Where(G => G.basic).Select(G => new Grocery
        {
            Id = G.Id,
            Timeout = G.Timeout
        }).ToList();

    }

}

该方法( )是CheckDBEvents(),它的作用是访问dbcontext实例并查找一些数据以保存到本地常量变量Called DataList

the method() is CheckDBEvents() and what it does is it accesses the dbcontext instance and looks for some data to save to to a local constant variable Called DataList

问题:每次我尝试将上下文(Dbcontext)实例(在控制器或任何其他类中)传递给CheckDBEvents()方法时,都会处理该上下文-DbContext Disposed Exception。
呼叫者

problem : every time i try passing the context (Dbcontext) instance --in the controller or any other class-- to the CheckDBEvents() method, the context is disposed -DbContext Disposed Exception. the caller

var t = new Alarm(db);
t.StartTimerEvent();

我的轮胎:-


  • 使警报成为静态类:

现在,如果我能做到的话令人惊异的...但无法在DbContext上进行操作,因为您无法在静态类中调用DbContext上的实例,因此您必须从调用它的人员那里传递它,从而导致相同的问题:db被Dispose并且不被传递

Now if i can do that It would be amazing ... but can not operate on DbContext since you can't call instance on DbContext in a static class you have to pass it from who ever calls it, which leads to the same problem :db is Disposed and don't get passed

        public static void StartTimerEvent(AppDbContext db)
    {
    .....

     // Hook up the Elapsed event for the timer. 
     aTimer.Elapsed += (source, e) => CheckDBEvents(source, e, db 
     //DbContext is Disposed here and
     //don't get passed'
     );

常量类和Dbcontext与我所读的内容也相处得不太好。

also constant classes and Dbcontext don't get along very well from what i have read.

长话短说
-我想将dbContext实例保留在另一个类中,而不是控制器中。
不会被处理。

Long Story Short -I want to keep instance of dbContext in another class rather than controllers. without it being disposed.

如果有人知道如何操作或拥有服务器端计时器的源代码或类似的东西,请发表评论,我被困了2天

if anyone have and idea what how to do this or have a source code to server side timer or anything like that please comment, I have been stuck for 2 days

推荐答案

最后我在多次测试后发现了问题,我需要参加
asp.net拥有的Strong Debedenty注入的优势,并将该类添加为服务,我也使用 IHostedService 作为我的服务类的接口,这是该服务的一个示例FinalTest(重命名为FinalTest的警报)

finally I have found the problem after many test, I needed to take advantage of the Strong Debedenty injection that asp.net have, and add the class as service, also I used IHostedService as interface for my service class, here is an example of the service FinalTest (renamed Alarm to FinalTest)

internal class FinalTest : IHostedService, IDisposable
{

    private Timer aTimer;
    public static List<Grocery> List;
    private AppDbContext db;
    // variable  to test that timer really works
    public static int test2;


    public FinalTest( AppDbContext _db )
    {
        db = _db;

    }

    //This method runs at the start of the application once only as FinalTest was set as Singleton in services
    public Task StartAsync(CancellationToken cancellationToken)
    {
        test2 = 1;
        aTimer =new Timer(CheckDBEvents, null , TimeSpan.Zero , TimeSpan.FromSeconds(10) );
        return Task.CompletedTask;
    }

    //Method runs every TimeSpan.FromSeconds(10)
    private void CheckDBEvents(object state)
    {

        var users = from u in db.Grocery where u.basic == true select u;
        List = users.ToList();
        //increase test2 To see changes in the real world
        test2++;
    }


    //--------shutdown operations---------//
    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        aTimer?.Dispose();
    }


}

现在,如果我将其注入服务 services.AddSingleton(FinalTest)中,因为我会得到范围异常,因为在SingleTon服务中使用作为范围服务的AppDbContext不好,不能有效地推广AppDbContext对于Singleton来说,这将来会引起问题,所以我不得不为AppDbContext创建另一个构造函数

Now if i injected this in the service services.AddSingleton(FinalTest) as it is I would get an scoped exceptions because using AppDbContext which is Scoped service in SingleTon service is not good and effectively promote AppDbContext To Singleton which is gonna cause problems in the future So I had to Create another constructor for AppDbContext

    public class AppDbContext : DbContext
{
    //Scoped constructor
    public AppDbContext(DbContextOptions<AppDbContext>  options) : base(options)
    {

    }

    //Singletone constructor
    public AppDbContext(DbContextOptions<AppDbContext> options,string connection)
    {
        connectionString = connection;
    }
    private string connectionString;
    //this is an override to OnConfiguring that's 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {

        if (connectionString != null)
        {
            var config = connectionString;
            optionsBuilder.UseSqlServer(config);
        }

        base.OnConfiguring(optionsBuilder);
    }
    //DbSet

    public DbSet<Grocery> Grocery { get; set; }

}

最后将两个 AppDbContext相加 FinalTest 到服务

 var connection = @"Server=(localdb)\mssqllocaldb;Database=FridgeServer.AspNetCore.NewDb;Trusted_Connection=True;ConnectRetryCount=0";
 services.AddDbContext<AppDbContext>(
            options => {
                //options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
                options.UseSqlServer(connection);
                //var config = Configuration["Data:DefaultConnection:ConnectionString"];

                //options.UseInMemoryDatabase("Grocery")
            }
        );

  services.AddSingleton<IHostedService,FinalTest>(s => new FinalTest(new AppDbContext(null, connection) ));

现在这是我的经验,而这一切都是有趣的经历,阅读有关依赖注入,Ioc和
编程的其他概念和模式,如果有人遇到某些问题,或者甚至想了解更多有关asp.net的信息,这里有一些帮助,第一个是最重要的。

Now that's my experience and it was all in all a fun experience reading all about Dependency injection and Ioc and other concept and pattern of programing if anyone face some of those problem or even want to know more about asp.net, here are some that helped ,the first one is the most important

http://deviq.com/category/principles/
http://deviq.com/dependency-inversion-principle/
https://docs.microsoft。 com / en-us / aspnet / core / fundamentals / dependency-injection?view = aspnetcore-2.1
在ASP .Net Singleton中使用DbContext注入的类
https://blogs.msdn.microsoft.com/cesardelatorre/2017/11/18/implementing-background-tasks-in -microservices-with-hostedservice-and-the-backgroundservice-class-net-core-2-x /

感谢@KienChu告诉我IHostedService,希望对您有所帮助

thanks to @KienChu for telling me about IHostedService , I Hope this helps someone

这篇关于具有DbContext的服务器端计时器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆