Почему NHibernate сохраняет новые объекты в неправильном порядке создания даже внутри транзакции? - PullRequest
1 голос
/ 09 февраля 2011

В моем приложении asp.net mvc есть объект Log, который отслеживает, что происходит на моем форуме.при добавлении комментария в транзакцию происходит следующее:

  1. Новый комментарий добавляется в таблицу представлений

  2. Новая запись в журнале сссылка на идентификатор этого комментария добавляется в таблицу журналов

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

Вот некоторый код, чтобы показать, чтопроисходит:

using (IAtomicTransaction Transaction = UnitOfWork.BeginTransaction())
{
    try
    {
        SubmissionRepository.AddComment(Comment, ParentSubmission);
        LogRepository.AddCommentEntry(Comment);            

        Transaction.Commit();
    }
    catch
    {
        Transaction.Rollback();
        throw;
    }
}

UnitOfWork и AtomicTransaction являются просто оболочками вокруг объектов ISession и ITransaction из API-интерфейсов NHibernate.И вот сгенерированный журнал, который подтверждает проблему:

2011-02-09 14:42:05,631 [15] DEBUG NHibernate.SQL - INSERT INTO logs (version, created_at, updated_at, comment_id) VALUES (?p0, ?p1, ?p2, ?p3); ?p0 = 9/02/2011 2:42:05 PM, ?p1 = 9/02/2011 3:41:52 AM, ?p2 = NULL, ?p3 = 0
2011-02-09 14:42:05,647 [15] DEBUG NHibernate.SQL - SELECT LAST_INSERT_ID()
2011-02-09 14:42:05,647 [15] DEBUG NHibernate.SQL - INSERT INTO submissions (version, created_at, updated_at, body) VALUES (?p0, ?p1, ?p2, ?p3);?p0 = 9/02/2011 2:42:05 PM, ?p1 = 9/02/2011 3:41:52 AM, ?p2 = 9/02/2011 3:41:52 AM, ?p3 = 'dfgdfgd dfg df'
2011-02-09 14:42:05,647 [15] DEBUG NHibernate.SQL - SELECT LAST_INSERT_ID()

Какое решение этой проблемы?

Обновление:

Так что оказалось, что если я позвонюПромывайте после каждой вставки, тогда порядок будет правильным.

using (IAtomicTransaction Transaction = UnitOfWork.BeginTransaction())
{
    try
    {
        SubmissionRepository.AddComment(Comment, ParentSubmission);
        UnitOfWork.CurrentSession.Flush();

        LogRepository.AddCommentEntry(Comment);            
        UnitOfWork.CurrentSession.Flush();

        Transaction.Commit();
    }
    catch
    {
        Transaction.Rollback();
        throw;
    }
}

1 Ответ

0 голосов
/ 09 февраля 2011

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

В исходном сообщении после добавления комментария нет "Сбросить", и вы хотите добавить журнал для этого комментария (для которого идентификатор еще не определен).

Не уверен, почему Nhibernate принимает такой обратный порядок, но кажется, что это как минимум проблема генерации ID.

Еще одна вещь, которая привлекла мое внимание, это то, что вы используете Comment и Args.Comment рядом. В чем разница?

В любом случае, если Comment является в некоторой степени вашей доменной сущностью, вы должны:

  • Вставьте его;
  • Убедитесь, что он подключен к текущему ISession (у вас должен быть доступный присоединенный к сеансу объект Comment объекта) ;
  • Используйте именно эту сущность (которая уже находится в хранилище) для записи в журнал (NHibernate позаботится о связях).
...