2016-04-15 2 views
1

У меня есть проблема с моей вставкой с NHibernateВставить молча завершаться NHibernate

Сделки начинается хорошо, Моими выбрать все сделано правильно, Мои выбрать следующее значение из последовательности тоже и совершать сделки, Но не вставить появляются в моем NHprofiler и никаких ошибок не появляется. Я использую Session.OpenSession (ReadCommited) & Сделки Любая идея о том, что происходит?

Код

class NHUnitOfWok : INHibernateUnitOfWork 
{ 
    private readonly ISession _session; 
    private bool _isDisposed; 
    private IsolationLevel _isolationLevel; 

    public NHUnitOfWok(ISession session) 
    { 
     _session = session; 
     _session.FlushMode = FlushMode.Never; 
     _isolationLevel = IsolationLevel.ReadCommitted; 
    } 

    internal ISession Session 
    { 
     get { return _session; } 
    } 

    public void SaveChanges() 
    { 
     Session.Flush(); 
    } 

    public void CancelChanges() 
    { 
     Session.Clear(); 
    } 

    public void Commit() 
    { 
     Session.Transaction.Commit(); 
    } 

    public void Rollback() 
    { 
     Session.Transaction.Rollback(); 
    } 


    public void WithinNewSession(Action<ISession> actionToExecute, IsolationLevel? isolationLevel = null) 
    { 
     using (var tempSession = Session.SessionFactory.OpenSession()) 
     { 
      using (var transaction = tempSession.BeginTransaction(isolationLevel ?? _isolationLevel)) 
      { 
       actionToExecute(tempSession); 
       transaction.Commit(); 
      } 
     } 
    } 

    public void WithinTransaction(Action action, IsolationLevel? isolationLevel = null) 
    { 
     Enforce.NotNull(action, "action"); 

     WithinTransaction<object>(() => 
     { 
      action(); 
      return null; 
     }); 
    } 

    public T WithinTransaction<T>(Func<T> func, IsolationLevel? isolationLevel = null) 
    { 
     Enforce.NotNull(func, "func"); 

     if (Session.Transaction != null && Session.Transaction.IsActive) 
     { 
      return func.Invoke(); 
     } 

     using (var localTran = Session.BeginTransaction(isolationLevel ?? _isolationLevel)) 
     { 
      try 
      { 
       var funcRes = func.Invoke(); 
       localTran.Commit(); 

       return funcRes; 
      } 
      catch (TransactionException ex) 
      { 
       throw new DataException(Resource.TransactionException, ex); 
      } 
      catch (Exception ex) 
      { 
       if (Session.Transaction.IsActive) 
        localTran.Rollback(); 
       throw new DataException(Resource.TransactionException, ex); 
      } 
     } 
    } 

    public bool IsStarted() 
    { 
     return Session.Transaction != null && Session.Transaction.IsActive; 
    } 

    public void Start() 
    { 
     if (Session.Transaction == null || !Session.Transaction.IsActive) 
     { 
      Session.BeginTransaction(_isolationLevel); 
     } 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!disposing || _isDisposed) 
     { 
      return; 
     } 
     _isDisposed = true; 
    } 

    #region IDisposable Members 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    #endregion 
} 
+1

пожалуйста, почтовый индекс. – Claudius

+1

Код, который вы используете для добавления своей сущности, также требуется, но в настоящее время не показан. –

+0

Он выбирает мой следующий вал из последовательности, но без вставки в мою транзакцию, очень странно – Arnaud

ответ

3

FlushMode.Never может быть хорошо для операции только для чтения, но для чего-то еще, ну, наверное, нет. Его XML-документации говорится:

ISession никогда не покраснел, если Flush() явно вызывается приложением. Этот режим очень эффективен для транзакций только для чтения.

Так что не используйте это по умолчанию.
Это мой совет, по крайней мере. Я знаю, что есть некоторые советы, скрывающиеся вокруг, чтобы использовать это для «производительности», но проверьте, есть ли у вас проблема, комментируя это.
Во всяком случае, я никогда не оптимизирую для производительности во время исполнения, производительность разработчика должна быть приоритетной, на мой взгляд. (Если приложение не имеет реальных, проверенных и соответствующих требований к производительности во время выполнения. Или, конечно, когда код является очевидным ужасом кодирования с точки зрения сложности выполнения во время выполнения, такой как немотивированные алгоритмы O (n²) или худшие.)

Если вы хотите придерживаться этого режима, позвоните по телефону Flush на сеансе перед совершением транзакций (или, как написано here by Andrew, выберите FlushMode.Commit). Но на самом деле этот выбор - ловушка для разработчиков, которые должны работать с ним.

смотрите документацию режима по умолчанию, Auto:

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

Желаете ли вы подвергнуть сомнению тонкие ошибки из-за получения неожиданно устаревших данных в запросах, происходящих в том же сеансе после некоторых изменений данных?

Боковое примечание: почему «усложняющий» код с Invoke? См. this.

+0

Большое спасибо, я смотрел вокруг транзакции и сессии, но забыл об этом !! – Arnaud

+0

'FlushMode.Auto' имеет свои недостатки. Неясно, когда сущности записываются в базу данных, и поэтому поведение промывки NHibernate трудно предсказать (т. Е. Производительность разработчика может быть затруднена непрозрачной смысловой семантикой). Здесь также стоит упомянуть «FlushMode.Commit». –

+0

В транзакционном контексте все может быть отменено, так что это не сильно изменится.Если разработчики не ожидают, что их изменения будут учтены в своих запросах, запущенных на одном сеансе, пока они явно не вызвали флеш. Но в этом случае проблема нехватки знаний о NHibernate. Теперь, если код использует сочетание запросов orm и sql-запросов при выполнении изменений в одном сеансе без явного флеша перед запросами ... Ну, это начинает быть бит-кромкой. (И для того, чтобы избежать «неожиданных» флешей, мы также должны советовать не использовать db-генерируемый PK.) –

Смежные вопросы