【问题标题】:Would like to execute a query once per day in ASP.NET MVC想在 ASP.NET MVC 中每天执行一次查询
【发布时间】:2011-07-09 01:30:06
【问题描述】:

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

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

编辑

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

编辑 2

更多细节:

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

【问题讨论】:

  • 如果您在专用服务器上运行您的网站,您可以考虑编写一个 Windows 服务来运行您的查询。这样您就不必担心 IIS 重新启动。即使您的网站由于某种原因关闭,您的服务仍然可以正常工作。

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


【解决方案1】:

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

RE:edit2:应该马上告诉。 SQL Server Compact 与 SQL Server 不同 - 一方面,它没有 SQL 代理 IIRC。尽管如此,调用 Web 层还是有点矫枉过正。我将 Windows 脚本宿主文件 (.js) 与 Windows 任务调度程序结合使用。 WSH 文件可以通过 ADO 连接到数据库并做任何他们想做的事情 - 插入、选择等等。

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

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

IIS 不是调度引擎。

Edit3 re:comment:抱歉,我误解了您设置的性质。我自己的经历影响了我的判断:)您能否在每次登录操作期间进行检查,如果自上次维护操作以来已经有一段时间,请立即运行它吗?维护需要多长时间?如果它是 ~1min+,那么在工作线程中运行它是有意义的,这样登录用户就不会等待。

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

【讨论】:

  • Seva,请看我的第二次编辑。我相信它确实需要在 web 层中。
  • 您仍然可以直接在 SQL Server 中执行您要查找的操作,或者通过运行在您的服务器上执行自定义 .exe 的计划任务。
  • @seva,感谢您更新您的答案。一个问题是我没有直接访问服务器机器的权限,只有 FTP 访问权限。我不确定我是否可以在无法上机的情况下实施您的解决方案。不过,如果您认为我将文件上传到网站目录完全可以完成,请告诉我。
  • @seva,在你知道你会得到什么样的答案之前,很难知道要提供什么细节:) 无论如何,谢谢你的帮助。我对你的“Edit2”有点困惑。在“MY end”运行调度是什么意思?我没有用于这个项目的专用机器,它一直在运行,所以我认为这对我不起作用。正如我在第一次编辑中所说,每次甚至在特定时间运行此查询并不重要,它只是需要“相当定期”完成的维护类型任务,并且每天似乎是一个很好的基本费率。 ..
  • (cont) 所以,我认为 global.asax 中的某种事件如果我正确设置它可能会为我的特定目的正常工作。如果没有人访问该网站以查看结果,我运行的查询将没有任何影响。因此,如果我安排在 7 月 11 日午夜,而 IIS 当时已关闭。如果查询直到有人在早上 8 点登录才运行,这很好......希望这能帮助您更好地理解我想要完成的工作。
【解决方案2】:

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

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

【讨论】:

  • gangelo,感谢您的回答。我会检查链接。请查看我的问题的编辑。
  • @danm,关于编辑:在这种情况下,如果不是那么关键,则无需存储在数据库中。如果您遇到困难,请给我发电子邮件,我可以在本周开始向您发送一些代码。顺便说一句,该示例未显示的是您需要检查时间的循环和“取消循环”机制以在应用程序端将其关闭。
【解决方案3】:

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

例如

我把我的任务放在 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 再次。

希望这有帮助:)

【讨论】:

    【解决方案4】:

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

    替代方案:

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

    【讨论】:

    • 阿列克谢,我部分根据您的回答在我的问题中添加了更多信息。我喜欢只检查每个请求的日期/时间并查看是否需要查询,然后运行它的想法。我想我可以用 ActionFilter 来做到这一点。你怎么看?
    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 2020-11-13
    • 2019-12-17
    • 2013-01-28
    相关资源
    最近更新 更多