Почему session.Clear () необходим для отражения изменений в БД в этом примере? - PullRequest
3 голосов
/ 18 июня 2010

У меня есть следующий код:

public class A
{
    private ISessionFactory _sf;
    A(ISessionFactory sf)
    {
        _sf = sf;
    }

    public void SomeFunc()
    {
        using (var session = _sf.OpenSession())
        using (var transaction = session.BeginTransaction())
        {
            // query for a object
            // change its properties
            // save the object

            transaction.commit();
        }
    }
}

Используется следующим образом в модульном тесте

_session.CreateCriteria ... // some setting up values for this test

var objectA = new A(_sessionFactory);
objectA.SomeFunc();

// _session.Clear();

var someVal = _session.CreateCriteria ... // retrieve value from db to 
                                   //check if it was set to the 
                                   //proper value
                                   //it uses a restriction on a property
                                   //and a uniqueresult to get the object.
                                   //it doesnt use get or load.

Assert.That(someVal, Is.EqualTo(someOtherValue)); // this is false as long 
                                   //as the _session.Clear() is commented. 
                                   //If uncommented, the test passes

Я проверяю базу данных sqlite . В своих тестах я вносил некоторые изменения в базу данных, чтобы правильно ее настроить. Затем я вызываю SomeFunc (). Это делает необходимые модификации. Как только я вернусь в свой тест, сеанс, однако, не получит обновленные значения. Он по-прежнему возвращает значение, как было до вызова SomeFunc (). Я должен выполнить _session.Clear (), чтобы изменения отразились в моем утверждении в тесте.

Зачем это нужно?

Редактировать: cache.use_second_level_cache и cache.use_query_cache установлены на false

Edit2 : Прочитайте следующие утверждения в документации NH .

Время от времени ISession будет выполнить операторы SQL, необходимые для синхронизировать соединение ADO.NET состояние с состоянием объектов проводится в памяти. Этот процесс, флеш, происходит по умолчанию в следующих точках

* from some invocations of Find() or Enumerable()
* from NHibernate.ITransaction.Commit()
* from ISession.Flush()

А в разделе 10.1 написано

Убедитесь, что вы понимаете семантику Промывать(). Промывка синхронизирует постоянное хранилище с оперативной памятью меняется, но не наоборот .

Итак, как мне получить объекты в памяти для обновления? Я понимаю, что объекты кэшируются за сеанс. Но выполнение UniqueResult () или List () должно синхронизироваться с БД и сделать кеш недействительным, верно?

Чего я не могу понять, так это почему данные сеанса представляют устаревшие данные?

Ответы [ 3 ]

0 голосов
/ 27 июля 2010

Просмотр объектов в памяти (кэш уровня 1) для каждой сессии.

A принимает ISessionFactory и открывает собственный сеанс со своей областью транзакций.

Даже если содержимое ISession, используемого в SomeFunc, сбрасывается в базу данных, _session не увидит эти изменения, пока его кэш уровня 1 не будет очищен.

0 голосов
/ 26 октября 2010

У вас есть две сессии.Один находится в A.SomeFunc, а другой - в вашем модульном тесте.Каждый сеанс имеет свой собственный экземпляр сущностей в кеше сеанса (кэш 1-го уровня).Сессии не общаются и не координируют друг друга.Когда один сеанс записывает свои изменения, другой сеанс не уведомляется.У него все еще есть собственный устаревший экземпляр в кеше сеанса.

Когда вы вызываете _session.Clear (), вы заставляете сеанс «забыть» обо всем, очистив кэш сеанса.При повторном запросе вы читаете свежие данные из базы данных, которая включает в себя изменения из другого сеанса.

0 голосов
/ 18 июня 2010

Это зависит от того, какой король операций вы делаете.NHibernate имеет кэш первого уровня по умолчанию.Он использует кеш для получения сущностей по ID и так далее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...