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;
}
}
Похоже, это работает отлично. Спасибо.