Продолжительность транзакции ASP.NET NHibernate - PullRequest
4 голосов
/ 29 сентября 2010

В настоящее время в нашем приложении ASP.NET у нас есть 1 сеанс на каждый запрос, и мы создаем одну транзакцию каждый раз, когда мы загружаем или обновляем и возражаем.См. Ниже:

    public static T FindById<T>(object id)
    {
        ISession session = NHibernateHelper.GetCurrentSession();
        ITransaction tx = session.BeginTransaction();
        try
        {
            obj = session.Get<T>(id);
            tx.Commit();
        }
        catch
        {
            session.Close();
            throw;
        }
        finally
        {
            tx.Dispose();
        }
        return obj;
    }

    public virtual void Save()
    {
        ISession session = NHibernateHelper.GetCurrentSession();
        ITransaction transaction = session.BeginTransaction();
        try
        {
            if (!IsPersisted)
            {
                session.Save(this);
            }
            else
            {
                session.SaveOrUpdateCopy(this);
            }
            transaction.Commit();

        }
        catch (HibernateException)
        {
            if (transaction != null)
            {
                transaction.Rollback();
            }
            if (session.IsOpen)
            {
                session.Close();
            }
            throw;
        }
        finally
        {
            transaction.Dispose();
        }

    }

Очевидно, что это не идеально, поскольку это означает, что вы создаете новое соединение с базой данных каждый раз, когда загружаете или сохраняете объект, что влечет за собой снижение производительности.

Вопросы:

  • Если объект уже загружен в кэш 1-го уровня, вызовет ли GetTransaction () соединение с базой данных?Я подозреваю, что это будет ...
  • Есть ли лучший способ обработки нашего управления транзакциями, чтобы было меньше транзакций и, следовательно, меньше соединений с базой данных?

К сожалению, код приложения, вероятно, слишкомсозрел, чтобы структурировать все так (с получением и обновлением всех в одной и той же транзакции):

using(var session = sessionFactory.OpenSession()) 
using(var tx = session.BeginTransaction()) 
{
    var post = session.Get<Post>(1);
    // do something with post
    tx.Commit();
} 

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

Ответы [ 2 ]

5 голосов
/ 29 сентября 2010

Одна транзакция на запрос считается наилучшей практикой с NHibernate.Этот шаблон реализован в Sharp Architecture .

Но в методе Nhibernate BeginTransaction() есть открытое соединение с БД.Соединение открывается при первом реальном запросе sql и закрывается сразу после выполнения запроса.Таким образом, Nhibernate удерживает открытое соединение в течение нескольких секунд для выполнения запроса.Вы можете проверить это с помощью SQL Profiler.

Кроме того, NHiberante всегда пытается использовать пул соединений Sql Servers, и поэтому открытие вашего соединения может быть не таким уж дорогим.

2 голосов
/ 29 сентября 2010

Было бы ужасной идеей создать одну транзакцию на запрос и зафиксировать ее в конце запроса

Это не было бы ужасно, но я думаю, что это плохая практика. Если есть ошибка и транзакция откатывается, я бы предпочел обработать ее на странице, а не в конце запроса. Я предпочитаю использовать один сеанс на запрос с таким количеством транзакций, которое мне нужно во время запроса (обычно одна).

NHibernate очень добросовестен в управлении соединениями с базой данных, вам не нужно беспокоиться об этом в большинстве случаев.

Мне не нравится ваша логика транзакции, особенно если вы прервете сеанс, если транзакция не удалась. И я не уверен, почему вы вызываете SaveOrUpdateCopy. NHibernate определит, нужно ли сохранить объект, поэтому проверка IsPersisted, вероятно, не нужна. Я использую этот шаблон:

using (var txn = session.BeginTransaction())
{
    try
    {
        session.SaveOrUpdate(this);
        txn.Commit();
    }
    catch (Exception ex)
    {
        txn.Rollback();
        // log
        // handle, wrap, or throw
     }
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...