是否可以在使用 NHibernate 的 Linq 提供程序加载的实体上设置只读模式?
例如,可以使用 Session.QueryOver 完成以下操作(我也相信使用 Criteria ):
Session.QueryOver(Of Foo)().ReadOnly()
是否有 Session.Query 的等价物可用?
是否可以在使用 NHibernate 的 Linq 提供程序加载的实体上设置只读模式?
例如,可以使用 Session.QueryOver 完成以下操作(我也相信使用 Criteria ):
Session.QueryOver(Of Foo)().ReadOnly()
是否有 Session.Query 的等价物可用?
要更改默认行为以便 NHibernate 将可变类的实体实例加载到会话中并自动将它们设为只读,请调用:
Session.DefaultReadOnly = true;
要更改默认值,以便 NHibernate 加载的实体不设为只读,请调用:
Session.DefaultReadOnly = false;
所以在调用Session.Query...
call之前Session.DefaultReadonly = true
,因为这个设置去到ISession
了 Provider 之上。
如果您需要只读会话,这里有更好的方法:如何在 nHiberate 中创建只读会话?
Session.DefaultReadOnly = true;
- 在这种情况下,NHibernate 将累积实体的所有更新(调用所有侦听器等)
session.FlushMode = FlushMode.Never
据我所知,在这种情况下,NHibernate 不会调用任何侦听器
根据标记答案的评论,该功能已在HN中实现,解决方案如下:
var result = await session
.Query<Company>()
.WithOptions(x => x.SetReadOnly(true))
.ToListAsync();
基于我的经验的最佳方法(隔离级别ReadCommitted)。以下会话不需要修改数据库:
// Readonly mode is used for running only READ queries without any changes. Flush mode is not needed.
using (var session = sessionFactory.WithOptions().FlushMode(FlushMode.Never).OpenSession())
{
session.DefaultReadOnly = true;
// Do your read only queries here
}
当需要进行一些修改但我们不想锁定不会被修改的表时,使用以下会话:
// The Flush (send all pending changes to the db) will be executed automatically on Commit.
using (var session = sessionFactory.WithOptions().FlushMode(FlushMode.Commit).OpenSession())
{
// Read committed with snapshot (https://stackoverflow.com/a/1664236/1143349)
using (var tran = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
// We are not modifiing settings so we can get a record in readonly mode
// Because of readonly, we do not lock the [settings] table for the time of that transaction.
// So, other sessions can use that table too at the same time.
var setting = session.Query<Setting>()
.WithOptions(x => x.SetReadOnly(true))
.Where(x => x.Key == "IsTenantRequired")
.SingleOrDefault();
if (setting?.Value == true)
{
var newTenant = new Tenant("My Tenant Name");
session.Save(newTenant);
}
// Do your other transactional changes
// but you promised to not touch the [settings] table (no modifications)
// in the current transaction.
tran.Commit();
} // Rollback happens here in case of errors
} // Session is closed here