0

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

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

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

任何类型的建议都会非常好,因为这对我来说是一个新概念,并且很想提出一个可靠的解决方案!

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

- 编辑 -

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

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

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

-- 编辑 晚上 8:30 --

所以我试图利用 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 中的时间量 - 此解决方案的问题是管理员将确定交易将显示多长时间,这意味着我需要基于缓存在那个值上。如果有人可以提供一些额外的帮助,我将非常感激!

根据詹姆斯约翰逊和我尝试过的其他人

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

但是,将 cacheData 设置为我的模型会返回 NullReferenceException。感叹我为什么要为此挣扎这么多嘿嘿。

4

3 回答 3

1

ASP.NET 不适合实现任何类型的计时功能。使用计划任务或服务,或将过期日期存储在服务器端存储介质之一(缓存、应用程序等)中,并在每次请求时检查它。

我建议使用 SqlDependency进行缓存:ASP.NET 应用程序中的 SqlDependency

编辑

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

Cache.Insert("AbsoluteCacheKey", cacheData, null, 
    DateTime.Now.AddMinutes(15), System.Web.Caching.Cache.NoSlidingExpiration);
于 2012-05-09T14:15:54.470 回答
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();
                } 
            }
        })
    }

如果有人知道刷新页面并加入新交易的更好方法,我会全力以赴!

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

于 2012-05-10T11:14:24.983 回答
0

我建议您将当前交易保存在缓存中,这样您就不必访问数据库。但是,那么,它在必要时将如何更新呢?好吧,简单的回答:将缓存的到期时间设置为交易完成的绝对时间,这样它就必须去数据库寻找新的交易。

伪代码:

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

要使用缓存,请查看:

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

于 2012-05-09T18:14:29.543 回答