在application_start中定时器切换当前交易'

时间:2012-05-09 14:07:40

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

一直试图找出完成这项任务的最佳方法,我会尝试尽可能直接地解释我的想法。

我正在使用类似于woot.com,whiskeymilitia.com等的网站,其中有一天或特定时间限制,IE:15分钟交易。我正在尝试创建一个计时器,该计时器将在应用程序每隔x秒开始运行,例如每5秒一次,并检查交易时间限制是否已经过去。

我目前正在查询数据库,以便为我提供应该显示的有效协议,但我不完全确定如何在Application_Start中实现这一点。基本上它会检查交易和交易限制时间+经过的时间,并确定是否在该点将该交易标记为非活动。是否可以将应用程序启动中的模型I查询路由到控制器?

任何建议都会很棒,因为这对我来说是一个新概念,我很乐意提出一个可靠的解决方案!

如果需要,请随时让我澄清任何事情!再次感谢:)

- 编辑 -

在查看SqlDependency后,我在测试完所有内容时遇到了错误。

未启用当前数据库的SQL Server Service Broker,因此不支持查询通知。如果您希望使用通知,请为此数据库启用Service Broker。 您的主机必须在您的数据库上启用SQL Service Broker。大多数共享环境托管公司似乎都避免这样做,并指出它对于专用服务器环境意味着更多。

寻找替代方案。想象一下,我会放弃它,让人们在遇到同样的事情之前达到顶峰。

- 编辑8:30 PM -

所以我试图利用Cache类来解决这个问题,但我只是完全卡住了。

    public ActionResult Index()
    {            

        CurrentDealModel model = new CurrentDealModel();

        model.DealQueueDetails = db.FirstOrDefault<ProductQueue>("SELECT * FROM ProductQueue WHERE Active = 1");

        model.ProductDetails = db.FirstOrDefault<Product>("WHERE Id = @0", model.DealQueueDetails.ProductId);

        return View(model);
    }

我想将这些数据缓存在控制器中,存储在变量model中的时间量.DealQueueDetails.DealTimeLimit - 此解决方案的问题在于管理员将确定交易显示的时间长度,这意味着我需要基于该值进行缓存。如果有人可以提供额外的帮助,我将非常感激!

Per James Johnson和其他人我试过

Cache.Insert(“AbsoluteCacheKey”,cacheData,null,     DateTime.Now.AddMinutes(15),System.Web.Caching.Cache.NoSlidingExpiration

但是,将cacheData设置为我的模型会返回NullReferenceException。叹了一下为什么我必须在这个hehe上挣扎这么多。

3 个答案:

答案 0 :(得分:1)

ASP.NET不是实现任何类型的计时功能的正确位置。使用计划任务或服务,或在其中一个服务器端存储介质(缓存,应用程序等)中存储过期日期,并在每个请求中进行检查。

我建议使用SqlDependency进行缓存:SqlDependency in an ASP.NET Application

修改

如果使用SqlDependency不在表中,只需设置绝对过期时间:

Cache.Insert("AbsoluteCacheKey", cacheData, null, 
    DateTime.Now.AddMinutes(15), System.Web.Caching.Cache.NoSlidingExpiration);

答案 1 :(得分:0)

我建议您将当前交易保留在缓存中,这样您就不必点击数据库了。但是,当necesasry时,它将如何更新?好的,简单的答案:在交易完成的绝对时间设置缓存的到期时间,这样就必须到数据库找到新的交易。

伪代码:

  public Deal GetDeal()
  {
      if (Cache contains deal)
          return deal from cache;
      else
      {
          get deal
          add deal to cache with absolute expiration
      }   
  }

要使用缓存,请查看:

通过此实现,您不必担心性能,轮询,服务器重启,依赖关系或其他任何问题。

答案 2 :(得分:0)

好吧,经过12个小时的修补和研究,我终于能够正确地实现这一点并且工作得很好这让我想开始担心它大声笑。

    public ActionResult Index()
    {

        ViewBag.Message = "Welcome to ASP.NET MVC!";

        CurrentDealModel model = new CurrentDealModel();

        model.DealQueueDetails = db.FirstOrDefault<ProductQueue>("SELECT * FROM ProductQueue WHERE Active = 1");

        model.ProductDetails = db.FirstOrDefault<Product>("WHERE Id = @0", model.DealQueueDetails.ProductId);
        var DealTime = model.DealQueueDetails.DealTimeLimit;
        var CurrentTime = System.DateTime.Now;

        TimeSpan span = DealTime.Subtract(CurrentTime);

        var model1 = HttpContext.Cache.Get(model.DealQueueDetails.Id.ToString());
        if (model1 == null)
        {
            model1 = HttpContext.Cache.Add(model.DealQueueDetails.Id.ToString(), model, null, System.DateTime.Now.Add(span).AddSeconds(10), Cache.NoSlidingExpiration, CacheItemPriority.High, new CacheItemRemovedCallback(RedirectToNewDeal));
            var CachedObject = HttpContext.Cache.Get(model.DealQueueDetails.Id.ToString());
            return View(CachedObject);
        }
        return View(model1);

    }

减去一些需要重命名的变量,并且有些变量需要重新考虑它才能完美运行。然后我将CacheItemRemovedCallback设置为以下函数。

    public static void RedirectToNewDeal(String key, Object item, CacheItemRemovedReason reason) 
    {
        DatabaseEntitiesDB db = DatabaseEntitiesDB.GetInstance();

        if(reason.ToString() == "Expired")
        {
            var QueueToDisable = db.FirstOrDefault<ProductQueue>("WHERE Id = @0", key);
            QueueToDisable.Active = false;
            QueueToDisable.Update();
        }
    }

还需要对此进行一些重构以及一些错误处理/日志记录,但是这已经按照我的预期进行了。现在除此之外唯一的事情就是我必须每隔3秒在主要的几个内部调用一个AJAX轮询方法来检查缓存,我就是这么做的。

     public ActionResult CacheCheck(string key)
    {
        var GetCachedObject = HttpContext.Cache.Get(key);

        if (GetCachedObject != null)
        {
            return Content("NotExpired");
        }
        return Content("Expired");

    }

AJAX致电

setTimeout(function () {
        setInterval(CacheCheck, 2000);
        CacheCheck();
    }, 10000);

function CacheCheck() {
        $.ajax({
            type: "POST",
            url: '@Url.Action("cachecheck", "home", new { key = Model.DealQueueDetails.Id })',
            success: function (data) {                    
                if (data == "Expired") {
                    window.location.reload();
                } 
            }
        })
    }

如果有人知道一个更好的方法来刷新页面并提出新的协议,我全都听见了!

感谢大家和他们的帮助,我希望这对其他人也有帮助!