Sqldependency事件MVC中的HttpContext.Current属性为null

时间:2014-04-17 13:59:05

标签: c# sql asp.net-mvc sqldependency

我正在开展一个多租户项目,每个租户都有自己的客户。目前我正在实施一个实时的东西,当任何客户注册或现有客户编辑他的个人资料信息时,我想实时通知该客户的租户(使用signalR)。

为了检测客户表格中的更改,我使用SqlDependencySqlTrigger。触发器将在通知表中进行输入(基本上包含一些受影响的Ids(如TenantId,CustomerId)和其他一些信息)并且在Sqldependency触发的事件中我调用的方法将使用signalR进一步调用客户端方法上下文。

现在我的问题是我无法在Sqldependency事件中访问HttpContext.Current线程,因为它没有执行请求。检查此图片:

enter image description here

如果我错了,请纠正我。我想访问此HttpContext.Current,因为我想访问当前的Tenant进行通知。我的TenantProvider实施从Url Host获得租户。

所以我的第一个问题是,有没有办法访问事件函数代码执行的上下文?

如果没有,那么我有另一种选择,有些疑惑。选项是我保存通知表中的更改,其中包含TenantId,CustomerId等信息。我可以使用最新的时间戳访问通知,从该条目我可以让tenantId通知。

现在怀疑是否有2个或更多客户同时注册并且在访问最新的时间戳通知条目之前,触发输入其他通知也比我们错过了一些通知。

所以我的第二个问题是我是否过度思考这个或者这真的是一个问题。如果这确实是一个问题,请告诉我解决方案?

2 个答案:

答案 0 :(得分:0)

我唯一担心你想要这样做的是你的更新的并发性,正是你描述的原因,解决方案是确保你使用跟踪中心的单个实例,以及您在集线器中修改的数据的并发字典。您使用通知表,这实际上是不必要的。

这里有一些示例链接,可以帮助您完成您的工作。 http://techbrij.com/database-change-notifications-asp-net-signalr-sqldependency http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-server-broadcast-with-signalr-20

第一个是sqldependency示例,第二个是中央服务器中心样式应用程序,它显示了如何进行线程安全的集中式集线器。

对于Httpcontext的问题,我使用了一个我保存在数据层中的辅助类,我使用一个存储库模式进行单线程集线器的开发。

这是我的班级。

using System.Web;

namespace DataLayer.Common
{
    public class ConnectionHelper : IConnectionHelper
    {
        private ApplicationDbContext _context;

        public ApplicationDbContext Context
        {
            get
            {
                if (_context == null && HttpContext.Current.Items["DbActiveContext"] != null)
                {
                    _context = (ApplicationDbContext)HttpContext.Current.Items["DbActiveContext"];
                }
                else if (_context == null && HttpContext.Current.Items["DbActiveContext"] == null)
                {
                    _context = new ApplicationDbContext();
                    HttpContext.Current.Items.Add("DbActiveContext", _context);
                }

                return _context;
            }
            set { _context = value; }
        }
    }
}

答案 1 :(得分:-1)

添加这两个步骤,以便您可以从HttpContext.Current.Session内部访问Customer_OnChange,我希望这会让您足够接近您需要的用户上下文。

首先,在实例化此类时,将HttpContext.Current.Session存储在属性中。这有助于您的实例记住当前会话。

HttpSessionState session;
public EntityChangeNotifier()
{
    session = HttpContext.Current.Session;
}

其次,在实例化此类之后,将新实例存储为会话变量。这样可以在整个用户会话中保持实例的活动。

EntityChangeNotifier ecn = new EntityChangeNotifier();
HttpContext.Current.Session["ecn"] = ecn;

现在您可以参考"会话"属于Customer_OnChange方法的属性。