C# 希望在ASP.NET MVC中每天执行一次查询

C# 希望在ASP.NET MVC中每天执行一次查询,c#,.net,asp.net-mvc,asp.net-mvc-3,.net-4.0,C#,.net,Asp.net Mvc,Asp.net Mvc 3,.net 4.0,我希望我的ASP.NET MVC应用程序每天执行一次查询。推荐的方法是什么 我的第一个想法是在Global.asax中设置一个计时器,它每24小时运行一次,然后从appeased处理程序调用我的查询。这样做有什么陷阱吗?有更好的办法吗 编辑 让我为我要做的事情补充一点细节。我特别希望查询在每天午夜执行。如果错过了一天(比如由于服务器维护或升级应用程序),那就不是什么大问题 编辑2 更多细节: 查询实际上是一个INSERT,而不是SELECT。目的是为月底到期续签其会员资格的任何会员添加“续签”记

我希望我的ASP.NET MVC应用程序每天执行一次查询。推荐的方法是什么

我的第一个想法是在Global.asax中设置一个计时器,它每24小时运行一次,然后从
appeased
处理程序调用我的查询。这样做有什么陷阱吗?有更好的办法吗

编辑

让我为我要做的事情补充一点细节。我特别希望查询在每天午夜执行。如果错过了一天(比如由于服务器维护或升级应用程序),那就不是什么大问题

编辑2

更多细节:

  • 查询实际上是一个INSERT,而不是SELECT。目的是为月底到期续签其会员资格的任何会员添加“续签”记录
  • 我使用的是SQLServerCompact(它是一个非常小的数据库)

  • 我在我的web应用程序中做这件事,但使用异步HTTP处理程序();我相信这是值得推荐的。我只是在应用程序启动时启动它,然后在应用程序端(Global.asx)关闭它


    需要记住的是,您可能必须在数据库中存储上次运行查询的时间,因为当您的应用程序池回收时,您将失去对该时间的跟踪。

    除非您有非常活跃的站点,否则IIS可能会关闭您的应用程序,并且没有执行任务的进程

    备选方案:

    • 只需在请求期间/请求后立即执行此操作,时间已足够接近
    • 通过GET/POST在您的站点上启动操作的外部任务
    • 将IIS重新配置为从不回收/停止应用程序池。比你的计时器有机会执行
    • 使用服务器上的一些外部服务来计划任务(“at”任务甚至SQL任务)

    它必须起源于Web层吗?谁会在那里消费HTML?通常,定期SQL查询在数据库中进行调度。对于MS SQL Server-通过SQL代理作业工具。SQL Server甚至可以发送电子邮件

    RE:edit2:我应该马上告诉你。SQL Server Compact与SQL Server不同——首先,它没有SQL代理IIRC。尽管如此,调用Web层还是有点过头了。我会将Windows脚本主机文件(.js)与Windows任务调度器结合使用。WSH文件可以通过ADO连接到数据库,并执行任何操作—插入、选择或任何操作

    要检测错过的计划运行,请引入一个包含计划运行日志的额外表。然后,在后续运行中,您可以分析最后一次运行的日期并相应地采取行动

    编辑2:所以没有管理权限。你真的应该说出问题中的所有细节。在这种情况下,我终究会通过Web层,但日程安排将在我这一方——我可以控制这一方。让任务调度器在您的终端上运行,并在服务器上调用HTTP URL。要调用URL,您可以使用如下内容。以预定的方式运行IE的缺点是让窗口保持打开状态

    IIS不是计划引擎

    Edit3 re:评论:对不起,我误解了您设置的本质。我自己的经验模糊了我的判断:)你能在每次登录操作期间运行一次检查吗?如果上次维护操作已经有一段时间了,请立即运行检查?保养需要多长时间?如果是~1min+,则可以在工作线程中运行它,这样登录用户就不会等待


    一般来说,安排日常维护是一个好主意,而且实施得相当频繁,但似乎您根本没有这种能力。

    我通过在“缓存”中放置一些虚假信息,然后设置我想要的时间段,然后处理“\u onCacheRemove”事件,做我想做的任何事情,然后重新创建“CacheItem”:

    e、 g

    我将我的任务放入枚举中,以秒为单位重新运行此任务:

    public enum ScheduledTasks
    {
        CleanGameRequests = 120,
        CleanUpOnlineUsers = 6
    }
    
    然后在“应用程序启动”处处理:

    注意:您可以根据需要进行时间管理。就我而言,我 希望每个周期都运行这些任务吗 不管时间是什么时候

    对你来说,你应该查一下时间 然后重新创建缓存项 再说一遍


    希望这有帮助:)

    gangelo,谢谢你的回答。我将查看链接。请查看对我的问题的编辑。@danm,关于编辑:在这种情况下,如果不是很关键,就不需要存储在数据库中。如果你卡住了,给我发电子邮件,我可以在本周初给你发一些代码。顺便说一句,该示例没有显示的是循环,您需要检查时间和“取消循环”机制,以便在应用程序端将其关闭。Seva,请参阅我的第二次编辑。我相信它确实需要在web层中。您仍然可以直接在SQL Server中执行所需的操作,也可以在服务器上运行一个执行自定义.exe的计划任务。@seva,感谢您更新答案。一个问题是我没有直接访问服务器的权限,只有FTP权限。我不确定我是否可以在无法进入机器的情况下实施您的解决方案。不过,如果您认为完全可以将我的文件上传到网站目录,请告诉我。@seva,在您知道您将得到什么样的答案之前,很难知道要提供什么样的详细信息:)无论如何,谢谢您的帮助。我被你的“编辑2”弄糊涂了。在“我的终点”运行调度是什么意思?我没有一台专门的机器来完成这个项目,它一直在运行,所以我认为这对我来说是行不通的。正如我在第一次编辑中所说,每次甚至在特定时间运行此查询并不重要,它只是一项需要“相当定期”完成的维护型任务,每天似乎是一个很好的基本速率…(续)因此,我认为global.asax中的某种事件可能会起作用
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RegisterRoutes(RouteTable.Routes);
    
            // Adding the tasks i want at App_Start 
            // so if the application restarted my task will refreshed.
            AddTask(ScheduledTasks.CleanGameRequests);
            AddTask(ScheduledTasks.CleanUpOnlineUsers);
        }
    
        // event to handel
        private static CacheItemRemovedCallback _onCacheRemove;
        private void AddTask(ScheduledTasks task)
        {
            _onCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
            HttpRuntime.Cache.Insert(task.ToString(), (int)task, null,
                DateTime.Now.AddSeconds((int)task), Cache.NoSlidingExpiration,
                CacheItemPriority.NotRemovable, _onCacheRemove);
        }
    
        public void CacheItemRemoved(string key, object time, CacheItemRemovedReason r)
        {
            var task = (ScheduledTasks)Enum.Parse(typeof(ScheduledTasks), key);
            switch (task)
            {
                case ScheduledTasks.CleanGameRequests:
                    // Do the concept that you wanna to do.
                    GameRequest.CleanUp();
                    break;
                case ScheduledTasks.CleanUpOnlineUsers:
                    OnlineUsers.CleanUp();
                    break;
                default:
                    break;
            }
    
    
            // Don't forget to recreate the "CacheItem" again.
            AddTask(task);
        }