我正在开展一个多租户项目,每个租户都有自己的客户。目前我正在实施一个实时的东西,当任何客户注册或现有客户编辑他的个人资料信息时,我想实时通知该客户的租户(使用signalR)。
为了检测客户表格中的更改,我使用SqlDependency和SqlTrigger。触发器将在通知表中进行输入(基本上包含一些受影响的Ids(如TenantId,CustomerId)和其他一些信息)并且在Sqldependency触发的事件中我调用的方法将使用signalR进一步调用客户端方法上下文。
现在我的问题是我无法在Sqldependency事件中访问HttpContext.Current线程,因为它没有执行请求。检查此图片:
如果我错了,请纠正我。我想访问此HttpContext.Current,因为我想访问当前的Tenant进行通知。我的TenantProvider实施从Url Host获得租户。
所以我的第一个问题是,有没有办法访问事件函数代码执行的上下文?
如果没有,那么我有另一种选择,有些疑惑。选项是我保存通知表中的更改,其中包含TenantId,CustomerId等信息。我可以使用最新的时间戳访问通知,从该条目我可以让tenantId通知。
现在怀疑是否有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
方法的属性。