NHibernate会话管理?

首先,让我简要介绍一下这个场景。 我正在编写一个简单的游戏,其中几乎所有工作都在服务器端完成,并且有一个瘦客户端供玩家访问。 玩家登录或创建帐户,然后可以通过在网格中移动来与游戏交互。 当他们进入一个小区时,他们应该被告知该小区中的其他玩家,同样地,该小区中的其他玩家将被告知该玩家进入该小区。 可以进行许多其他交互和操作,但是不值得详细介绍它们,因为它更加相同。 当玩家退出然后重新登录或者如果服务器停机并重新启动,则所有游戏状态都应该持续存在,但是如果服务器崩溃,那么如果我失去10分钟左右的更改则无关紧要。

我已经决定使用NHibernate和一个SQLite数据库了,所以我在NHibernate上阅读了很多内容,按照教程和编写了一些示例应用程序,我对如何应对这个问题感到非常困惑!

我的问题是:管理会话的最佳方式是什么? 只是从我理解的少量,所有这些可能性跳出来对我:

  • 拥有一个始终打开的会话,所有客户端都使用该会话
  • 为每个连接并定期刷新它的客户端设置一个会话
  • 每次我必须使用任何持久化实体时打开一个会话,并在更新,插入,删除或查询完成后立即关闭它
  • 为每个客户端建立一个会话,但保持断开状态,只有在需要使用它时才重新连接
  • 与上面相同,但保持连接状态,并在一段时间不活动后才断开连接
  • 保持实体分离,并且每隔10分钟仅附加一次,例如,提交更改

我可以使用什么样的策略来获得不错的性能,因为每秒可能有数百个客户端可能会有很多更新,插入,删除和查询,而且它们都必须相互一致?

另一个小问题:我应该如何以有效的方式使用交易? 是否可以将每一次更改都放在自己的事务中,或者当我有数百个客户端都在尝试更改网格中的单元格时,这种情况会不会很糟糕? 我是否应该尝试弄清楚如何将类似的更新批量放在一起并将它们放在一个单独的事务中,还是会变得太复杂? 我甚至需要大部分交易吗?

我将每个请求使用一个会话到服务器,每个会话一个事务。 在应用程序成熟之前,我不会针对性能进行优化。

回答您的解决方案:

  • 有一个始终打开的会话,所有客户端都使用:这里会遇到性能问题,因为会话不是线程安全的,您必须锁定对会话的所有调用。
  • 为每个连接并定期刷新它的客户端设置一个会话:这里会出现性能问题,因为客户端使用的所有数据都将被缓存。 您还将看到缓存中过时数据的问题。
  • 每次我必须使用任何持久化实体时打开一个会话,并在更新,插入,删除或查询完成后立即关闭它:这里不会有任何性能问题。 缺点是可能并发或损坏数据问题,因为相关的sql语句不在同一事务中执行。
  • 为每个客户端建立一个会话,但保持断开状态,只在我需要使用它时重新连接它:NHibernate已经内置了连接管理,并且已经非常优化。
  • 与上面相同,但保持连接并且仅在一段时间不活动后断开它:将导致问题,因为sql连接的数量有限并且还将限制应用程序的用户数量。
  • 保持实体分离,并且每隔10分钟仅附加一次,例如,提交更改:由于分离实体中的陈旧数据,将导致问题。 您必须自己跟踪更改,这使您最终得到一段看起来像会话本身的代码。

现在详细介绍一下是没用的,因为我只想重复手册/教程/书。 当您按请求使用会话时,您可能不会在您描述的99%的应用程序中遇到问题(可能根本不会)。 Session是一个轻量级而不是线程安全的类,它的寿命非常短。 如果您想确切了解会话/连接/缓存/事务管理的工作原理,我建议您首先阅读手册,然后再询问有关不清楚主题的更详细问题。

阅读NHibernate文档页面上的“ ISessionFactory ”。 ISession意味着是单线程的(即,不是线程安全的),这可能意味着您不应该跨用户共享它。 应用程序应创建一次ISession并为每个工作单元创建ISession 。 请记住,创建ISession并不一定会导致打开数据库连接。 这取决于SessionFactory的连接池策略的配置方式。

您可能还想查看Hibernate关于会话和事务的文档。

我的目标是将所有内容保存在内存中,并且日志更改或定期脱机快照。

通过ASP.NET阅读NHibernate最佳实践 ,这里有一些非常好的技巧可供选择。 如上所述已经非常小心ISession,因为它不是线程安全的,所以请记住这一点。

如果你需要更复杂的东西,那么看看NHibernate.Burrow contrib项目。 它表示类似“Burrow提供的真正function是Burrow会话可以跨越多个http请求”。