nhibernate-сеанс для веб-запроса с Castle.Facility.AutoTx и Castle.Facility.NHibernate всегда создает новый сеанс при openseesion - PullRequest
0 голосов
/ 11 января 2019

Я использую Castle Windors, и это AutoTx и NHibernate Facility. Как я и ожидал, каждый HTTP-запрос The Facility будет поддерживать сеанс базы данных для всего процесса. вот мой конфиг для Facility:

        <factory id="icost.factory" alias="nh.facility.default">
            <settings>

      <add key="log4net.Internal.Debug" value="true"/>

      <add key="hibernate.show_sql" value="false" />
      <item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item>
                <item key="connection.driver_class">NHibernate.Driver.OracleDataClientDriver</item>
      <item key="dialect">#{nhibernateDialect}</item>
                <item key="connection.connection_string_name">#{connectionStringName}</item>
      <item key="cache.provider_class">NHibernate.Cache.HashtableCacheProvider, NHibernate</item>          
                <item key="cache.use_second_level_cache">true</item>
                <item key="cache.use_query_cache">true</item>
                <item key="relativeExpiration">300</item>
      <item key="command_timeout">12000</item>
      <item key="adonet.batch_size">250</item>
      <item key="generate_statistics">false</item>
      <item key="max_fetch_depth">5</item>
      <item key="generate_statistics">false</item>
      <add key="connection.isolation" value="ReadUncommitted" />
      <add key="current_session_context_class">managed_web</add>
      <item key="hbm2ddl.keywords">none</item>          
      <item key="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</item>
      <!-- Speed things up -->
      <item key="use_proxy_validator">false</item>
      <item key="show_sql">true</item>
            </settings>

            <assemblies>
      <assembly>Business</assembly>                 
            </assemblies>

        </factory>
    </facility>

В моем коде есть 2 функции извлечения и сохранения, которые используют ISessionManager

private readonly ISessionManager _sessionManager;
public virtual T FetchFirst(ICriteria criteria)
    {
        using (ISession session = _sessionManager.OpenSession(_SessionFactoryAlias))
        {
            var list = (GetExecutableCriteria(session, criteria)
                        .SetFirstResult(0)
                        .SetMaxResults(1)
                        .List<T>());

            return (list.Count > 0  ? list[0] : default(T));
        }
    }

public virtual void Save(T entity)
    {
        using (ISession session = _sessionManager.OpenSession(_SessionFactoryAlias))
        {
            session.Save(entity);
        }
    }

Вот как я использую вышеуказанные функции в своем коде:

ReportValue entity = repository.FetchFirst(criteria);            
// do some change
repository.Save(entity);

Все прошло хорошо. Я проверяю идентификатор сеанса для действия извлечения и сохранения действия, которые совпадают

{9a046635-ad11-4208-86ce-8de800a4649a} //fetch
{9a046635-ad11-4208-86ce-8de800a4649a} //save

Но когда я пытаюсь провести стресс-тест и одновременный запрос в моих вкладках. Ошибка возникает. Сеанс отличается при сохранении и получении

{3c8eca53-6000-4db7-a20b-5dc437ce4aaf} //fetch
{82f4a60a-c142-4b0b-97f2-89170a8a77fa} //save

Я попробовал Google реализовать код реализации для ISessionManager. Я обнаружил, что этот репозиторий является наиболее совместимым кодом для ISessionManager. https://github.com/castleproject-deprecated/Castle.Facilities.NHibernateIntegration-READONLY/blob/master/src/Castle.Facilities.NHibernateIntegration/DefaultSessionManager.cs

public ISession OpenSession(String alias)
    {
        if (alias == null) throw new ArgumentNullException("alias");

        ITransaction transaction = ObtainCurrentTransaction();

        SessionDelegate wrapped = sessionStore.FindCompatibleSession(alias);

        ISession session;

        if (wrapped == null)
        {
            session = CreateSession(alias);

            wrapped = WrapSession(transaction != null, session);
            EnlistIfNecessary(true, transaction, wrapped);
            sessionStore.Store(alias, wrapped);
        }
        else
        {
            EnlistIfNecessary(false, transaction, wrapped);
            wrapped = WrapSession(true, wrapped.InnerSession);
        }

        return wrapped;
    }

На основе кода реализации код будет найден в хранилище сеансов для текущего сеанса. Итак, я пытаюсь в окне отладки исследовать SessionDelegate. И получить результат "session store.FindCompatibleSession (alias)" всегда будет нулевым. Это означало, что где-то в коде. Это явное «хранилище сеансов» неожиданно.

Я использую .Net v4.7.2. Есть ли какие-либо несовместимые для Facility lib и .Net версии. Потому что эта библиотека довольно старая, 6 лет назад.

Любая помощь очень ценится.

...