Должен ли я явно сбрасывать сессию после «SaveOrUpdate»? - PullRequest
2 голосов
/ 14 января 2010

Я написал тест интеграции, который не проходит:

    [Test]
    public void Find_WorkItemWithMatchingDescriptionExistsInRepository_ReturnsWorkItem()
    {
        // arrange
        WorkItemRepository repository = new WorkItemRepository(IsolatingFactory);

        const string Description = "A";
        WorkItem itemWithMatchingDescription = WorkItem.Create(1, Description);
        repository.Commit(itemWithMatchingDescription);

        // act
        List<WorkItem> searchResult = repository.Find(Description);

        // assert
        CollectionAssert.Contains(searchResult, itemWithMatchingDescription);
    }

При просмотре вывода sql из nhibernate я замечаю, что он создает оператор select для операции repository.Find (), но не выполняет операцию вставки перед выбором. Если я поставлю явный session.Flush () после репозитория. Commit, он работает как положено, но я считаю это поведение странным. Почему nhibernate не сбрасывает сеанс автоматически, когда есть ожидающая вставка и выполняется запрос к сеансу?

Я нашел это в документации:

9,6. Flush

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

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

Похоже, что поведение nhibernate по умолчанию сбрасывается перед запросом по find. Мой репозиторий использует Ling для nhibernate для спецификации запроса, возможно, это ошибка.

Обновление

Если я изменю свое отображение с:

    public WorkItemClassMap()
    {
        Not.LazyLoad();

        Id(wi => wi.Id).GeneratedBy.Assigned();
        Map(wi => wi.Description).Length(500);
        Version(wi => wi.LastChanged).UnsavedValue(new DateTime().ToString());
    }

Кому:

    public WorkItemClassMap()
    {
        Not.LazyLoad();

        Id(wi => wi.Id).GeneratedBy.Identity();
        Map(wi => wi.Description).Length(500);
    }

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

Ответы [ 3 ]

3 голосов
/ 14 января 2010

Вы должны использовать разные ISession экземпляры для вставки и выбора методов. Лучше всего, если эти сеансы находятся в блоке using, так что они правильно расположены внутри транзакции базы данных:

using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
    // perform your insert here
    tx.Commit();
}
2 голосов
/ 15 января 2010

WorkItem в вашем примере сопоставлен с составным идентификатором? Я только что написал простой тест. Мой фиктивный класс будет автоматически очищаться, когда у меня будет один столбец идентификаторов. Я написал тот же тест, но с составным идентификатором, и получил поведение, которое вы описали выше.

0 голосов
/ 14 января 2010

Предполагается, что ваш репозиторий вял или создает сеанс, который уже существует. Когда вы создаете WorkItem и фиксируете его, он просто переходит в список заданий для этого сеанса. Если ваш репозиторий не создает транзакцию, а ваш метод commit не поддерживает явную фиксацию транзакции. Затем обновление или сохранение будут ждать до закрытия сеанса, поэтому, хотя вы можете видеть созданный вами объект, вы не сможете получить, например, идентификатор области, пока не закроете сеанс или не очистите его. Конечно, searchResult ничего не будет знать об объекте, который вы создали, без транзакции сброса или закрытия.

Существуют опасности с транзакциями, аналогичными сеансам в целом, но если вы создаете новые объекты, вам следует использовать явные транзакции. NHProfiler с готовностью предупредит вас об этом.

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