想在ASP.NET MVC中每天执行一次查询

时间:2011-07-09 01:30:07

标签: c# .net asp.net-mvc asp.net-mvc-3 .net-4.0

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

我的第一个想法是在Global.asax中放置一个每24小时启动一次的计时器,然后从Elapsed处理程序调用我的查询。这样做有什么陷阱吗?还有更好的方法吗?

修改

让我为我正在尝试做的事情添加一些细节。我特别喜欢每天午夜执行的查询。如果错过了一天(例如由于服务器维护或升级应用程序),这不会是一个主要问题。

修改2

更多细节:

  1. 查询实际上是INSERT,而不是SELECT。目的是为任何将在月底续订其会员资格的会员添加“续订”记录。
  2. 我正在使用SQL Server Compact(它是一个非常小的数据库)。

4 个答案:

答案 0 :(得分:8)

是否必须来自Web层?谁会在那里使用HTML?通常,在数据库中调度定期SQL查询。对于MS SQL Server - 通过SQL Agent作业工具。 SQL Server甚至可以发送电子邮件。

RE:edit2:应该马上告诉我们。 SQL Server Compact与SQL Server不同 - 例如,它没有SQL Agent IIRC。尽管如此,调用Web层仍然是一种过度杀伤力。我将Windows Scripting Host文件(.js)与Windows任务调度程序结合使用。 WSH文件可以通过ADO连接到数据库,并做任何他们想做的事 - 插入,选择,任何东西。

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

Edit2:所以没有管理员权限。你应该真正告诉问题中的所有细节。在这种情况下,我 毕竟会通过Web层,但调度将在我的结束 - 我有控制权。在您的端部运行任务计划程序并在服务器上调用HTTP URL。要调用URL,您可以使用free CURL utility之类的内容。以预定方式运行IE具有使窗口保持打开的缺点。

IIS不是一个调度引擎。

Edit3 re:评论:对不起,我误解了你的设置的性质。我自己的经历使我的判断蒙上阴影:)你可以在每次登录操作时运行一次检查,如果从上次维护操作开始已经有一段时间了,那么就在那里运行吗?维修需要多长时间?如果它是〜1min +,则在工作线程中运行它是有意义的,这样登录用户就不会等待。

一般来说,安排日常维护是一个好主意,并且它经常被实施,但似乎你根本没有这种能力。

答案 1 :(得分:1)

我在我的网络应用程序中执行此操作,但使用异步HTTP处理程序(http://msdn.microsoft.com/en-us/library/ms227433.aspx#Y512);我相信这会被推荐。我只是在应用程序启动时启动它并在应用程序端关闭它(Global.asx)。

要记住的是,您可能必须存储查询在数据库中最后一次运行的时间,因为当您的应用程序池回收时,您将忽略该查询。

答案 2 :(得分:1)

我这样做是通过在“缓存”中放入一些虚假信息并将我想要的时间段放入“_onCacheRemove”事件,然后做我想做的事情,然后再次重新创建“CacheItem”:

e.g。

我把我的任务放在Enum中,我想在几秒钟内重新运行这个任务:

public enum ScheduledTasks
{
    CleanGameRequests = 120,
    CleanUpOnlineUsers = 6
}

然后在“Application_Start”中处理它们:

    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);
    }
  

注意:您可以根据需要进行时间管理。在我的情况下我   想要在每个时期运行这些任务   时间,不管时间是什么。

     

在你的情况下,你应该检查时间   之前重新创建CacheItem   试。

希望这有助于:)

答案 3 :(得分:0)

除非您有非常活跃的网站,否则IIS会将您的应用程序关闭,并且将无法执行您的任务。

备选方案:

  • 只是在时间足够接近的请求期间/之后立即执行此操作
  • 有外部任务,将通过GET / POST触发您网站上的操作。
  • 重新配置IIS以永远不会回收/停止您的应用池。比你的计时器有机会执行。
  • 在服务器上使用一些外部服务来安排任务(“at”甚至SQL任务)。