Nhibernate: обработка исключений ITransaction, чтобы новые транзакции могли продолжаться с одинаковым ISession

У меня есть список из 10 объектов данных, которые я хочу вставить/обновить в базу данных с помощью NHibernate. Если кто-то генерирует исключение (например, нарушение первичного ключа), я хочу по-прежнему вставлять/обновлять остальные 9. Я перевернул каждую операцию объекта в свою собственную атомную транзакцию и откатил транзакцию, если есть исключение. Проблема заключается в том, что если транзакция вызывает исключение и откатывается назад, на следующей транзакции Nhibernate жалуется на ошибку: null id в записи Nexus.Data.PortfolioCorporateEntity (не сбрасывать сеанс после возникновения исключения)

Моя основная программа проста. Он создает сеанс из sessionfactory, создает уровень доступа к данным, выполняет некоторую работу над объектами данных и затем пытается сохранить эти объекты данных в базе данных.

    sessionsManager = new NHibernateSessionManager();
        session = sessionsManager.GetSession();
        DALC = new NHibernateDataProvider(session);

        …

        foreach (var pce in pces)
        {
            try
            {
                DALC.UpdateOrAddObject<PortfolioCorporateEntity>(pce);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not add Corporate Entity ID " + pce.CorporateEntity.CorporateEntityID.ToString());
            }

        }

Это процедура updateOrAdd на моем уровне доступа к данным Nhibernate, называемая 10 раз для 10 объектов.

public void UpdateOrAddObject<T>(T workObject) 
{ 
    using (ITransaction tx = mSession.BeginTransaction) { 
        try { 
            mSession.SaveOrUpdate(workObject); 
            mSession.Flush(); 
            tx.Commit(); 
        } 
        catch (Exception ex) { 
            tx.Rollback(); 
            throw;
        } 
    } 
} 

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

public NHibernateDataProvider(ISession session) 
{ 
    mSession = session; 
} 

Это отлично работает, за исключением исключения, он говорит, что не очищает сеанс после исключения. Я не уверен, почему - транзакция была отменена красиво, и база данных должна быть готова принять другую транзакцию нет? Что я делаю неправильно?

Ответ 1

Невозможно повторно использовать сеанс NHibernate после генерирования исключения. Цитата документации:

If the ISession throws an exception you should immediately rollback the
transaction, call ISession.Close() and discard the ISession instance.
Certain methods of ISession will not leave the session in a consistent state.

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

Ответ 2

Я очищаю сессию, и она продолжается нормально


ISession session = NHibernateHelper.Session;
using (ITransaction transaction = session.BeginTransaction())
{
    try
    {
        session.Update(user, user.UserID);
        transaction.Commit();
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        session.Clear();
        throw new DALException("Cannot update user", ex);
    }
}

Ответ 3

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

        foreach (var pce in pces)
        {
            try
            {
                DALC.UpdateOrAddObject<PortfolioCorporateEntity>(pce);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not add Corporate Entity ID " + pce.CorporateEntity.CorporateEntityID.ToString());

                session.Close();
                session = sessionsManager.GetSession();
                DALC.Session = session;

            }
        }

Похоже, это работает отлично. Спасибо.