Nhibernate 信号器OnDisconnected事件未将数据持久化到数据库
我有一个signarhub,我在其中注入服务类,这些服务类通过castlewindsor将数据持久化到本地sqlserver实例 该中心看起来像:Nhibernate 信号器OnDisconnected事件未将数据持久化到数据库,nhibernate,fluent-nhibernate,asp.net-mvc-5,signalr,castle-windsor,Nhibernate,Fluent Nhibernate,Asp.net Mvc 5,Signalr,Castle Windsor,我有一个signarhub,我在其中注入服务类,这些服务类通过castlewindsor将数据持久化到本地sqlserver实例 该中心看起来像: [Authorize] public class MyHub : Hub { private readonly IHubService _hubService; private readonly IHubUserService _hubUserService; private readonly IUserService _u
[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方法激发时,不会从数据库中删除任何内容。我可以看到代码确实执行了,但记录仍保留在数据库中,不会被删除
我想知道我的nhibernate会话是否由于castle windsor的依赖生存期或其他原因而没有将事务提交到数据库,然而,奇怪的是,LeaveHub按预期执行,但OnDisconnected方法中没有相同的代码
根据博客文章,我的依赖项注册为以下配置
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()
);
Kernel.Register(
//Nhibernate会话工厂
Component.For().UsingFactoryMethod(CreateNhSessionFactory).lifety.Singleton,
//Nhibernate会议
Component.For()
);
我还注册了一个拦截器来实现工作单元模式:
// Unitofwork interceptor
Component.For<NhUnitOfWorkInterceptor>().LifeStyle.HybridPerWebRequestTransient()
//Unitofwork拦截器
Component.For()
如果有人能给出方法LeaveHub正确工作的原因以及它无法在OnDisconnected方法中持久化任何内容的原因,我们将不胜感激。仅供参考,Nhibernate会话使用async做得不太好,因为它们根本不是线程安全的。试着同步运行,看看你得到了什么 Nhibernate是否设置为事务提交时刷新?我不能评论,因为我是一个新手,但我在不久前遇到了这个问题。我没有使用FluentNhibernate,但我确信有一个配置选项可以在事务提交时设置flush。这是假设您正在事务中包装所有打开的会话调用。我用这样的东西来治疗。去拿Nhibernate档案器吧,这是天赐之物
public class SessionManager : ISessionManager
{
private readonly ISessionFactory _sessionFactory;
private ISession _currentSession;
private ITransaction _currentTransaction;
public SessionManager(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public ISession OpenSession()
{
if (CurrentSessionContext.HasBind(_sessionFactory))
{
_currentSession = _sessionFactory.GetCurrentSession();
}
else
{
_currentSession = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(_currentSession);
}
CurrentSessionContext.Bind(_currentSession);
_currentTransaction = _currentSession.BeginTransaction();
return _currentSession;
}
public void Dispose()
{
try
{
if (_currentTransaction != null && _currentTransaction.IsActive)
_currentTransaction.Commit();
}
catch (Exception)
{
if (_currentTransaction != null) _currentTransaction.Rollback();
throw;
}
finally
{
if (_currentSession != null)
{
if (_currentTransaction != null) _currentTransaction.Dispose();
_currentSession.Close();
}
}
}
}
这是我的配置,我正在几个应用程序上使用它。从另一方面来说,我没有理由不使用FluentNhibernate,内置代码的映射非常棒而且灵活。让我知道我可以给你发送一些示例映射
public class SessionFactoryBuilder
{
public static ISessionFactory BuildSessionFactory(string connectionString)
{
var cfg = new Configuration();
cfg.DataBaseIntegration(db =>
{
db.Dialect<MsSql2012Dialect>();
db.Driver<Sql2008ClientDriver>();
db.ConnectionString = connectionString;
db.BatchSize = 1500;
db.LogSqlInConsole = false;
db.PrepareCommands = true;
db.ConnectionReleaseMode = ConnectionReleaseMode.AfterTransaction;
db.IsolationLevel = IsolationLevel.ReadCommitted;
})
.SetProperty(Environment.CurrentSessionContextClass, "web")
.SetProperty(Environment.UseSecondLevelCache, "true")
.SetProperty(Environment.ShowSql, "true")
.SetProperty(Environment.PrepareSql, "true")
.Cache(c =>
{
c.UseQueryCache = true;
c.Provider<RtMemoryCacheProvider>();
c.DefaultExpiration = 1440;
}).SessionFactory().GenerateStatistics();
HbmMapping mapping = GetMappings();
cfg.AddDeserializedMapping(mapping, "AppName");
SchemaMetadataUpdater.QuoteTableAndColumns(cfg);
return cfg.BuildSessionFactory();
}
private static HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.AddMappings(typeof (UserMap).Assembly.GetTypes());
HbmMapping mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
return mapping;
}
}
我只是猜测,因为我没有足够的上下文,但是由于您使用的是task,您是否确定OnDisconnected在UnitOfWork发布之前完成。我不相信OnDisconnected在UnitOfWork发布之前完成。拦截器在存储库级别截取所有方法,因此UnitOfWork在OnDisconnected中在我的服务调用
\u hubUserService.RemoveHubUser(hubUser)中启动和完成代码>我相信在您的拦截器实现中,您有一些类似于提交当前trunsaction的东西?你能把breakepoint放在那里吗?也许看看Sql事件探查器中发生了什么?我可以看到事务在我期望的时候提交。我将尝试使用NHibernate探查器进行更深入的挖掘。在日志中,NHibernate在OnDisconnected方法期间不执行任何查询。我相信这可能与我如何管理会话有关。我将尝试这种方法来管理会话,也许它会解决问题。因此,在我的存储库类中,我应该注入ISessionManager,并在构造函数中调用_sessionManager.OpenSession()?实现您的方法非常有效,但在OnDisconnected方法期间仍然存在相同的问题。我在这一行得到一个空对象错误:if(CurrentSessionContext.HasBind(\u sessionFactory))
。调试显示my_sessionFactory不是空的,因此我仍然不确定问题所在。请将您的上下文设置为web环境。在您的nhibernate配置中设置为CurrentSessionContextClass,“web”。您现在要让我使用信号器创建一些内容,对吗。LOLI对生活方式有点好奇。HybridPerWebRequestTransient()为什么生活方式PerWebRequest不起作用?
public class SignalRDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver
{
private readonly IWindsorContainer _container;
public SignalRDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public override object GetService(Type serviceType)
{
return TryGet(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return TryGetAll(serviceType).Concat(base.GetServices(serviceType));
}
[DebuggerStepThrough]
private object TryGet(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception)
{
return null;
}
}
private IEnumerable<object> TryGetAll(Type serviceType)
{
try
{
Array array = _container.ResolveAll(serviceType);
return array.Cast<object>().ToList();
}
catch (Exception)
{
return null;
}
}
}
// SignalR
_container.Register(Classes.FromThisAssembly().BasedOn(typeof(IHub)).LifestyleTransient());
SignalRDependencyResolver signalRDependencyResolver = new SignalRDependencyResolver(_container);
Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver = signalRDependencyResolver;