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

4
我希望我的ASP.NET MVC应用程序每天执行一次查询。建议的方法是什么?
我的第一个想法是在Global.asax中放置一个定时器,每24小时触发一次,然后从Elapsed处理程序调用我的查询。这样做有什么缺点吗?还有更好的方法吗?
编辑
让我补充一些我要做的细节。我特别希望查询每天午夜执行。如果错过了一天(例如由于服务器维护或升级应用程序),那也不是什么大问题。
编辑2
还有几个细节:
1. 查询实际上是一个插入操作,而不是选择操作。目的是为即将在月底续费的任何会员添加“续订”记录。 2. 我正在使用SQL Server Compact(它是一个非常小的数据库)。

如果您的网站运行在专用服务器上,您可以考虑编写一个Windows服务来运行查询。这样,您就不必担心IIS重新启动的问题。即使您的网站由于某种原因而停机,您的服务仍将继续工作。 - matrix
4个回答

8

它必须起源于Web层吗?谁会消费HTML?通常,在数据库中安排定期SQL查询。在MS SQL Server的情况下,可以通过SQL Agent作业工具来进行安排。SQL Server甚至可以发送电子邮件。

关于编辑2:应该立即告知。SQL Server Compact与SQL Server不同-首先,我IRC没有SQL Agent。尽管如此,调用Web层是一种过度设计。我将使用Windows脚本主机文件(.js)与Windows任务计划程序配合使用。WSH文件可以通过ADO连接到数据库并执行任何操作-插入,选择,任何操作。

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

编辑2: 没有管理员访问权限。你应该在问题中详细说明所有这些细节。在这种情况下,我仍然会通过Web层进行调度,但是调度将在我的端点上进行控制。让任务计划程序在您的端点上运行,并在服务器上调用HTTP URL。要调用URL,您可以使用类似于免费CURL实用程序的东西。以计划方式运行IE的缺点是窗口保持打开状态。

IIS不是调度引擎。

编辑3回复评论: 对不起,我误解了您设置的性质。我的经验使我的判断变得模糊:) 您能否在每次登录操作期间进行检查,如果距离上次维护操作已经有一段时间,则立即运行它?维护需要多长时间? 如果超过1分钟,最好在工作线程中运行它,以便不会让登录用户等待。

通常情况下,安排每天进行维护是一个好主意,并且经常实施,但似乎您没有这个能力。


Seva,请看一下我的第二次编辑。我认为它确实需要在Web层中。 - devuxer
你仍然可以直接在SQL Server中完成你想要的操作,或者通过运行定时任务,在服务器上执行自定义的.exe文件来实现。 - Chase Florell
@seva,感谢您更新您的答案。一个问题是我没有直接访问服务器机器的权限,只有FTP访问权限。我不确定在无法登录机器的情况下是否能够实现您的解决方案。请告诉我您是否认为可以完全通过上传文件到网站目录来完成。 - devuxer
@seva,在你不知道会得到什么样的答案之前,很难知道要提供哪些细节 :) 无论如何,感谢你的帮助。我有点困惑你的“Edit2”。你所说的在“我的端口”运行调度是什么意思?我没有专门为这个项目运行的机器,所以我认为这对我来说行不通。正如我在第一个编辑中所说的,这个查询并不需要每次都运行,甚至不需要在特定时间运行,它只是一项需要“相当经常”完成的维护任务,每天似乎是一个不错的基础频率... - devuxer
因此,我认为在global.asax中设置某种事件可能非常适合我的特定目的,如果我设置得当。如果没有人访问网站查看结果,则我运行的查询将不会产生影响。因此,如果我安排在7月11日午夜,并且此时IIS宕机,那么直到某个人在早上8点登录之前,查询都不运行也是可以的。希望这可以帮助您更好地理解我想要实现的目标。 - devuxer

1

我是通过在“缓存”中放置一些虚假信息并设置所需的时间段,然后处理“_onCacheRemove”事件来执行我想要的操作,然后重新创建“CacheItem”来实现这一点:

例如:

我将我的任务与我想要重新运行此任务的时间(以秒为单位)放在枚举中:

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。

希望对您有所帮助 :)

1

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

需要记住的是,您可能需要在数据库中存储上次查询运行的时间,因为当应用程序池重新启动时,您将失去跟踪。


gangelo,感谢您的回答。我会查看链接。请查看我问题的编辑。 - devuxer
@danm,关于编辑:在这种情况下,如果不是非常重要,就不需要存储在数据库中。如果你卡住了,请给我发电子邮件,我可以在下周初发送一些代码给你。顺便说一句,那个示例没有显示你需要检查时间和“取消循环”机制以在应用程序结束时关闭它的循环。 - gangelo

0

除非你的网站非常活跃,否则IIS会使你的应用程序崩溃,并且没有进程来执行你的任务。

替代方案:

  • 在/紧接着请求期间执行此操作
  • 拥有外部任务,可以通过GET/POST触发您网站上的操作。
  • 重新配置IIS以永不回收/停止您的应用程序池。 然后您的计时器有机会执行。
  • 使用服务器上的某些外部服务来安排任务("at"或甚至SQL任务)。

Alexei,我根据你的回答,在我的问题中添加了一些更多的信息。我喜欢检查每个请求的日期/时间并查看是否需要查询的想法,如果需要,则运行它。我在考虑能否使用ActionFilter完成这个想法。你觉得呢? - devuxer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接