6

是否可以在使用 NHibernate 的 Linq 提供程序加载的实体上设置只读模式?

例如,可以使用 Session.QueryOver 完成以下操作(我也相信使用 Criteria ):

Session.QueryOver(Of Foo)().ReadOnly()

是否有 Session.Query 的等价物可用?

4

3 回答 3

8

如文档10.1.2 中所述。以只读方式加载持久实体

要更改默认行为以便 NHibernate 将可变类的实体实例加载到会话中并自动将它们设为只读,请调用:

Session.DefaultReadOnly = true;

要更改默认值,以便 NHibernate 加载的实体不设为只读,请调用:

Session.DefaultReadOnly = false;

所以在调用Session.Query...call之前Session.DefaultReadonly = true,因为这个设置去到ISession了 Provider 之上。

于 2013-05-29T17:12:46.853 回答
2

如果您需要只读会话,这里有更好的方法:如何在 nHiberate 中创建只读会话?

Session.DefaultReadOnly = true;- 在这种情况下,NHibernate 将累积实体的所有更新(调用所有侦听器等)

session.FlushMode = FlushMode.Never

据我所知,在这种情况下,NHibernate 不会调用任何侦听器

于 2015-01-11T18:28:31.627 回答
0

根据标记答案的评论,该功能已在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
于 2021-09-28T14:32:09.137 回答