Не очищать сеанс после возникновения исключения – NHibernate

StackOverflow https://stackoverflow.com/questions/1819034

  •  10-07-2019
  •  | 
  •  

Вопрос

Я разрабатываю веб-приложение ASP.NET MVC под .NET 3.5, NHibernate и размещаю его в Windows Azure.Когда веб-приложение запускается из локальной среды разработки, оно работает нормально.Тем не менее, когда я перемещаю его в Windows Azure, каждая вставка, выполняемая из веб-роли MVC, заканчивается исключением, указанным ниже.

Есть идеи, что не так с моей логикой NHibernate?(может быть, управление сеансом, не уверен)

[УтверждениеОшибка:NULL ID в LOKAD.TransLate.Enterities.ser Вход (не промывайте сеанс после возникновения исключения)] nhibernate.event.default.defaultflushentityeventlistener.checkid (Object obj, IentityPersister, идентификатор объекта, EntityMode) +292 nhibernate. Event.Default.DefaultFlushEntityEventListener.GetValues(Object entity, EntityEntry entry, EntityMode entityMode, Boolean mightBeDirty, ISessionImplementor session) +93 NHibernate.Event.Default.DefaultFlushEntityEventListener.OnFlushEntity(FlushEntityEvent event) +158 NHibernate.Event.Default.AbstractFlushingEventListener.FlushEntities( Event Flushevent) +469 nhibernate.event.default.abstractflushingeventlistener.flusheveryThingToExections (Event FlushEvent) +339 nhibernate.event.Default.DefaultflusheventListener.Onflush (Event FlushEvent) +85 NHIBERNATE.SessionImplusher.Flush (flushEvent Event) +85. Adotransaction.commit () +236 lokad.translate.repositories.pagerepository.create (страница страницы) lokad.translate.controllers.pagescontroller.create (страница страницы) lambda_method (exeportionscope, controllerbase, Object []) +69 System.Web.MVC. .ReflectactActionDescriptor.execute (ControlerContext ControlerContext, Idictionary2 parameters) +251 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 параметры) +31 System.Web.mvc. <> C__displayclassa.b__7 () +88 System.web.mvc.controlleractionInvoker.invokeactionMethodFilter (IActionFilter Filter, ActionExeCutingContext, Func1 continuation) +534 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 фильтры, ActionDescriptor actionDescriptor, IDictionary`2 параметры) 312 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 856 System.Web.Mvc.Controller.ExecuteCore() 185 System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) 221 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 586 System.Web.HttpApplication.ExecuteStep(IEexecutionStep step, Boolean& completedSynchronously) 177

Обратите внимание, что я использую _session.FlushMode = FlushMode.Commit; и что User используется в пользовательском RoleProvider

public class SimpleRoleProvider : RoleProvider 
{
    readonly UserRepository Users = new UserRepository();

    public override string[] GetRolesForUser(string username)
    {
        try
        {
            var user = Users.Get(username);

            // no role if user is not registered
            if (null == user) return new string[0];

            // default role for registered user
            return user.IsManager ? new[] { "Manager", "User" } : new[] { "User" };
        }
        catch (Exception)
        {
            // role should not fail in case of DB issue.
            return new string[0];
        }
    }
}
Это было полезно?

Решение 2

Наконец-то я нашел решение своей собственной проблемы.Если кому-то будет интересно, выкладываю решение здесь.

public class SimpleRoleProvider : RoleProvider 
{
    // isolated session management for the RoleProvider to avoid
    // issues with automated management of session lifecycle.

    public override string[] GetRolesForUser(string username)
    {
        using (var session = GlobalSetup.SessionFactory.OpenSession())
        {
            var users = new UserRepository(session);
            var user = users.Get(username);

            // no role if user is not registered
            if (null == user) return new string[0];

            // default role for registered user
            return user.IsManager ? new[] {"Manager", "User"} : new[] {"User"};
        }
    }
}

По сути, то, что происходило, заключалось в том, что RoleProvider Репозиторий, похоже, не имеет такого же жизненного цикла, как обычные репозитории в представлении/в контроллере.В результате на момент вызова RoleProvider сеанс NHibernate уже был удален, что привело к исключению, наблюдаемому здесь выше.

Я заменил код на следующий здесь выше.У этого есть собственное управление сеансами NHibernate, и в конечном итоге он работает нормально.

Другие советы

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

Я пытаюсь объяснить, почему.

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

Учтите, что решения и вычисления в вашем коде основаны на значениях в памяти..Но в случае игнорируемого исключения эти значения не являются значениями в базе данных, их там никогда не будет.Таким образом, ваша логика будет принимать решения и рассчитывать на «фэнтезийные данные».

Кстати, никогда не стоит перехватывать какие-либо исключения (нетипизированные) и игнорировать их..Вы всегда должны знать, какие исключения вы обрабатываете, и быть уверены, что сможете продолжить.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top