NHibernate ISession.Save () - Почему это сохраняет мои сущности сразу? - PullRequest
4 голосов
/ 26 июня 2011

Я создаю большое количество сущностей с помощью NHibernate, присоединяю их к моей сессии ISession и затем использую транзакцию для фиксации моих изменений в базе данных. Пример кода ниже:

ISession _context = SessionProvider.OpenSession();

//Create new entities
for(int i=0; i<100; i++)
{
    MyEntity entity = new MyEntity(i);

    //Attach new entity to the context
    _context.Save(entity);
}

//Persist all changes to the database
using(var tx = _context.BeginTransaction())
{
    //Flush the session
    tx.Commit();
}

У меня сложилось впечатление, что строка _context.Save () просто информирует ISession о новой сущности, но изменения в базе данных не сохраняются до тех пор, пока я не сброслю сеанс с помощью строки tx.Commit ().

Однако я заметил, что база данных получает новую сущность каждый раз, когда я вызываю _context.Save (). В результате я получаю слишком много отдельных обращений к базе данных.

Кто-нибудь знает, почему ISession.Save () автоматически сохраняет изменения? Я неправильно понял что-то о том, как ведет себя NHibernate? Спасибо.

*** РЕДАКТИРОВАТЬ - Просто чтобы уточнить (в свете двух предложенных ответов) - моя проблема здесь в том, что база данных обновляется, как только я вызываю _context.Save (). Я не ожидаю, что это произойдет. Я ожидаю, что ничего не будет вставлено в базу данных, пока я не вызову tx.Commit (). К сожалению, ни один из двух предложенных ответов пока не помогает в этом.

Некоторую полезную информацию о генераторах идентичности можно найти здесь

Ответы [ 6 ]

7 голосов
/ 26 июня 2011

Попробуйте:

using(Session _context = SessionProvider.OpenSession())
using(var tx = _context.BeginTransaction())
{
    //Create new entities
    for(int i=0; i<100; i++)
    {
        MyEntity entity = new MyEntity(i);

        //Attach new entity to the context
        _context.Save(entity);
    }

    //Flush the session
    tx.Commit();
}
6 голосов
/ 26 июня 2011

Какой генератор идентичности вы используете? Если вы используете генераторы после вставки, такие как MSSQL / MySQL Identity или Oracle sequence, для генерации значений полей Id, это ваша проблема.

Из Выявлены генераторы POID NHibernate :

Пост вставьте генераторы, как имя предложить, присваивает идентификаторы после сущность хранится в базе данных. оператор выбора выполняется против база данных. У них много недостатков, и по моему они должны быть использованы только на коричневых проектах. Те генераторы - это то, что МЫ НЕ ПРЕДЛАГАЕМ как NH Team .

Некоторые из недостатков Следующий

  1. Единица работы нарушается с использованием эти стратегии. Неважно, если вы используете FlushMode.Commit, каждый Сохранить результаты в инструкции вставки против БД. Как лучшая практика, мы следует отложить вставки в коммит, но с помощью пост-генератора вставки заставляет его совершать сохранение (что к чему UoW не делает)
  2. Эти стратегии аннулировать дозатор, вы не можете взять Преимущество отправки нескольких запросов сразу (как это должно идти в базу данных в время сохранения)
2 голосов
/ 27 июня 2011

Вы можете установить размер партии в вашей конфигурации:

<add key="hibernate.batch_size" value="10" /> 

Или вы можете установить его в коде. И убедитесь, что вы делаете свои сохранения в рамках транзакции.

1 голос
/ 27 июня 2011

Попробуйте установить для FlushMode значение Commit:

ISession _context = SessionProvider.OpenSession();
context.FlushMode = FlushMode.Commit;

Предложение пэра установить размер партии также хорошо.

Насколько я понимаю, при использовании столбцов идентификаторов базы данных NHibernate будет откладывать вставки до тех пор, пока не будет сброшен сеанс, если только ему не нужно выполнить вставку для извлечения внешнего ключа или обеспечения того, что запрос возвращает ожидаемые результаты.

0 голосов
/ 27 июня 2011

Ну

  1. ответ мятежника возможен в зависимости от вашего отображения
  2. вы не используете явные транзакции (ответ StuffHappens)
  3. режим сброса по умолчанию - автоматическийи это усложняет ситуацию (ответ Jamie Ide)
  4. , если при каких-либо изменениях вы делаете какие-либо запросы, используя API-интерфейс nhibernate, поведение по умолчанию - сначала сбросить кэш в базу данных, чтобы результаты этих запросов соответствовали сеансупредставление сущности.
0 голосов
/ 26 июня 2011

А как же:

ISession _context = SessionProvider.OpenSession();

//Persist all changes to the database
using(var tx = _context.BeginTransaction())
{
    //Create new entities
    for(int i=0; i<100; i++)
    {
        MyEntity entity = new MyEntity(i);

        //Attach new entity to the context
        _context.Save(entity);
    }

    //Flush the session
    tx.Commit();

}
...