【发布时间】:2014-08-26 13:54:01
【问题描述】:
我有一个 SignalR 集线器,我在其中注入服务类,这些服务类通过 Castle Windsor 将数据持久保存到本地 SQL Server 实例。
集线器的样子:
[Authorize]
public class MyHub : Hub
{
private readonly IHubService _hubService;
private readonly IHubUserService _hubUserService;
private readonly IUserService _userService;
public MyHub(IHubService hubService, IHubUserService hubUserService, IUserService userService)
{
_hubService = hubService;
_hubUserService = hubUserService;
_userService = userService;
}
public async Task JoinHub(Guid hubId)
{
var hub = _hubService.GetHubById(hubId);
if (hub == null)
throw new NotFoundException(String.Format("Hub ({0}) was not found.", hubId.ToString()));
var userName = Context.User.Identity.Name;
var user = _userService.GetUserByUserName(userName);
if (user == null)
throw new NotFoundException(String.Format("User ({0}) was not found.", userName));
var hubUser = new HubUser
{
User = user,
Hub = hub,
ConnectionId = Context.ConnectionId
};
// Persist a new HubUser to the DB
hubUser = _hubUserService.InsertHubUser(hubUser);
await Groups.Add(Context.ConnectionId, hub.Id.ToString());
Clients.Group(hub.Id.ToString()).addChatMessage(userName + " has joined.");
}
public async Task LeaveHub()
{
var userName = Context.User.Identity.Name;
var hubUser = _hubUserService.GetHubUserByUserName(userName);
// Removes HubUser from the DB
_hubUserService.RemoveHubUser(hubUser);
await Groups.Remove(Context.ConnectionId, hubUser.Hub.Id.ToString());
Clients.Group(hubUser.Hub.Id.ToString()).addChatMessage(userName + " has left.");
}
public override Task OnDisconnected(bool stopCalled)
{
var userName = Context.User.Identity.Name;
var hubUser = _hubUserService.GetHubUserByUserName(userName);
// Removes HubUser from the DB
_hubUserService.RemoveHubUser(hubUser); // This line executes but does not persist anything to DB
Groups.Remove(Context.ConnectionId, hubUser.Hub.Id.ToString());
Clients.Group(hubUser.Hub.Id.ToString()).addChatMessage(userName + " has left.");
return base.OnDisconnected(stopCalled);
}
}
从客户端调用 JoinHub 和 LeaveHub 方法时,一切正常。但是,当 OnDisconnected 方法触发时,不会从数据库中删除任何内容。我可以看到代码确实执行了,但是记录保留在数据库中并且没有被删除。
我想知道我的休眠会话是否由于城堡 Windsor 的依赖生命周期或其他原因而没有将事务提交到数据库,但是,奇怪的是 LeaveHub 按预期执行但相同的代码没有在 OnDisconnected 方法中。
根据this 博客文章,我的依赖项使用以下配置注册。
Kernel.Register(
//Nhibernate session factory
Component.For<ISessionFactory>().UsingFactoryMethod(CreateNhSessionFactory).LifeStyle.Singleton,
//Nhibernate session
Component.For<ISession>().UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>().OpenSession()).LifeStyle.HybridPerWebRequestTransient()
);
我还注册了一个拦截器来实现工作单元模式:
// Unitofwork interceptor
Component.For<NhUnitOfWorkInterceptor>().LifeStyle.HybridPerWebRequestTransient()
如果有人可以就 LeaveHub 方法为何正确工作以及为什么它无法在 OnDisconnected 方法中保留任何内容提供任何意见,我们将不胜感激。
【问题讨论】:
-
我只是在猜测,因为我没有足够的上下文,但由于您使用的是任务,您确定 OnDisconnected 在 UnitOfWork 发布之前完成。
-
我不相信 OnDisconnected 在 UnitOfWork 发布之前完成。拦截器拦截存储库级别的所有方法,因此 UnitOfWork 在我的服务调用
_hubUserService.RemoveHubUser(hubUser);中的 OnDisconnected 内启动和完成 -
我相信在你的拦截器实现中你有类似提交当前截断的东西?你可以在那里放置断点吗?也许看看 Sql profiler 中发生了什么?
-
我可以看到事务在我期望的时候提交。我将尝试使用 NHibernate Profiler 进行更深入的研究。在日志中 NHibernate 在 OnDisconnected 方法期间没有执行任何查询。我相信这可能与我管理会话的方式有关。
标签: nhibernate fluent-nhibernate asp.net-mvc-5 signalr castle-windsor