2016-07-26 13 views
5

Я использую NHibernate в приложении MVC C# с MySQL. Я пытаюсь, чтобы несколько пользователей получили доступ к сеансу. Я использую .InRequestScope() на своей сессии, но я все еще получаю:Сессия закрыта. Имя объекта: «ISession». в NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - Как остановить сеанс от преждевременного закрытия

System.ObjectDisposedException: сессия закрыта! Имя объекта: «ISession». в NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() *

... или ошибки DataReader, когда у меня есть мои коллеги всех навигации на ту же страницу, что обращается Услуга в то же время.

Мой IMasterSessionSource инъекции

Bind<IMasterSessionSource>().To<GeneralMasterSessionSource() 
          .InRequestScope(); 

Мой IContentService где мои отображения становятся обслуживаются

 //ContentService Bingings 
     Bind<IContentService>().To<ContentService>().InRequestScope(); 
     Bind<ISession>() 
      .ToMethod(
       context => 
        context.Kernel.Get<IMasterSessionSource>() 
         .ExposeConfiguration() 
         .BuildSessionFactory() 
         .OpenSession() 
      ) 
      .WhenInjectedInto<IContentService>() 
      .InRequestScope(); 

ContentService

public interface IContentService 
    { 
     IQueryable<Question> Questions{ get; } 
    } 


public class ContentService : IContentService 
    { 
     private readonly ISession _session; 

     public ContentService(ISession session) 
     { 
      _session = session; 
     } 

     public IQueryable<Question> Questions 
     { 
      get { return _session.Query<Question>(); } 
     } 
    } 

DetailsService

public interface IDetailsService 
    { 
     IEnumerable<Question> PullQuestions(); 
    } 

public class DetailsService : IDetailsService 
    { 
     private readonly IContentService _contentService; 


     public GeneralService(IContentService contentService) 
     { 
      _contentService = contentService; 
     } 

     public IEnumerable<Question> PullQuestions() 
     { 
      var result = _contentService.Questions; 
      return result; 
     } 
} 

CONTROLLER

public class Test: Controller 
    { 

     private readonly IContentService _contentService; 
     private readonly IGeneralService _generalService; 

     public CollegeController(IContentService contentService, IDetailsService detailsService) 
     { 
      _contentService = contentService; 
      _detailsService = detailsService; 
     } 

     public ActionResult Index() 
     { 
      { 
       var model = new HomePageContent 
       { 
        Questions = _detailsService.PullQuestions().ToList(); 
       }; 
      } 
     } 
    } 

МОДЕЛЬ

public class HomePageContent 
    { 
     public IEnumerable<Question> Questions { get; set; } 
    } 

VIEW

foreach(var question in Model.Questions){ 
@Html.Raw(question.Question) 
} 

Так что для одного пользователя, посещающего эту страницу. Все работает нормально. Но когда mutliple пользователей visist той же страницы, каждый получает ошибку:

{ «Существует уже открытая DataReader, связанная с этим соединением, которое должно быть закрыто первым.»} { "Существует уже открытая DataReader, связанная с это соединение, которое должно быть закрыто первым. "} {« Нет текущего запроса в считывателе данных »} {« Нет текущего запроса в считывателе данных »} {« Существует уже открытый DataReader, связанный с этим соединением, который должен быть закрыт первым . "} {" Сессия закрыта! \ R \ nОбъект: "ISession".}

Я уже добавил InRequestScope. Я даже добавил эту реализацию: NHibernate, and odd "Session is Closed!" errors

но я все еще получаю Сессии закрыты! ошибки. Я даже пытался создать новый Kernel.Get, если сеанс был закрыт, но проблема в том, что ошибка иногда возникает даже тогда, когда сеанс открыт. Пожалуйста помоги! Я в конце концов с этим вопросом, и я не могу найти решение в любом месте. Я почти думаю, что NHibernate невозможно обрабатывать сразу несколько сеансов.

UPDATE

Может быть, есть способ ждать захороненных сессии перед открытием нового?

Трассировка стека

[ObjectDisposedException: Сессия закрыта! Название объекта:. 'ISession'] NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() +192
NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() +55 NHibernate.Impl.AbstractSessionImpl.CreateQuery (IQueryExpression QueryExpression) +171
NHibernate.Linq.DefaultQueryProvider.PrepareQuery (выражение выражение, IQuery & запроса, NhLinqExpression & nhQuery) +226
NHibernate.Linq.DefaultQueryProvider.Execute (выражение выражение) +80 NHibernate.Linq.DefaultQueryProvider.Execute (выражение выражение) + 74 Remotion.Linq.QueryableBase 1.GetEnumerator() +193 System.Collections.Generic.List 1..ctor (IEnumerable 1 collection) +432 System.Linq.Enumerable.ToList(IEnumerable 1 источник) +70
Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsService.FindItems (String пункт, контроллер String) в C: \ Users \ WD \ Desktop \ мастер \ Gcus.PublicGeneralSite.Data. Core \ Service \ General \ DetailsService.cs: 724 Gcus.Com.Web.Controllers.CoursesController.Details (String category, String item) в c: \ Users \ wd \ Desktop \ master \ Gcus.Com.Web \ Контроллеры \ CoursesController.cs: 213 lambda_method (Закрытие, ControllerBase, Object []) +366
System.Web.Mvc.ActionMethodDispatcher.Execute (ControllerBase контроллер, Object [] параметры) +87
System.Web.Mvc .ReflectedActionDescripto r.Execute (ControllerContext controllerContext, IDictionary параметры) +93
System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod() +97 System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39 (IAsyncResult AsyncResult, ActionInvocation innerInvokeState) +53
System.Web.Mvc.Async.WrappedAsyncResult 2.CallEndDelegate(IAsyncResult asyncResult) +137
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult AsyncResult, Object тег) +136
System .Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod (IAsyncResult asyncResult) +76
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__3d() +164 System.Web.Mvc.Async. <> c__DisplayClass46.b__3f() +549 System.Web.Mvc.Async. <> c__DisplayClass33.b__32 (IAsyncResult AsyncResult) +75
System.Web.Mvc.Async.WrappedAsyncResult 1.CallEndDelegate(IAsyncResult asyncResult) +79
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +187
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult AsyncResult, Объект Тег) +136
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters (IAsyncResult AsyncResult) +76
System.Web.Mvc.Async. <> c__DisplayClass2b.b__1c() +114 System.Web.Mvc.Async. <> c__DisplayClass21.b__1e (IAsyncResult AsyncResult) +306
System.Web.Mvc.Async.WrappedAsyncResult 1.CallEndDelegate(IAsyncResult asyncResult) +75
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult AsyncResult, Объект тегов) +72
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction (IAsyncResult AsyncResult) + 60
System.Web.Mvc.Controller.b__1d (IAsyncResult AsyncResult, ExecuteCoreState innerState) +70
System.Web.Mvc.Async .WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +135
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc.Async.Asyn cResultWrapper.End (IAsyncResult AsyncResult, Объект Тег) +72
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult AsyncResult, Объект тегов): +51
System.Web.Mvc.Controller.EndExecuteCore (IAsyncResult AsyncResult) +66 System.Web.Mvc.Controller.b__15 (IAsyncResult AsyncResult, контроллер контроллер) + 60
System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +98
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc. Async.AsyncResultWrapper.End (IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult asyncResul т, тег объекта): +51 System.Web.Mvc.Controller.EndExecute (IAsyncResult AsyncResult) + 60
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute (IAsyncResult AsyncResult) +60
System.Web.Mvc.MvcHandler.b__5 (IAsyncResult AsyncResult, ProcessRequestState innerState) +70
System.Web.Mvc.Async.WrappedAsyncVoid 1.CallEndDelegate(IAsyncResult asyncResult) +135
System.Web.Mvc.Async.WrappedAsyncResultBase
1.End() +176
System.Web.Mvc. Async.AsyncResultWrapper.End (IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End (IAsyncResult asyncResult, тег Object) +51
System.Web.Mvc.MvcHandler.EndProcessRequest (IAsyncResult AsyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest (IAsyncResult результат) +59
системы. Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +399 System.Web.HttpApplication.ExecuteStep (IExecutionStep шаг, Boolean & completedSynchronously) +137

+0

NHibernate, безусловно, не имеет проблем с несколькими параллельными сеансами. Фактически, он предназначен для обработки именно этого сценария. Однако он не может обрабатывать одновременный доступ к сеансу _single_. Сеанс не является потокобезопасным. Вы, кажется, знаете об этом, так как вы говорите о InRequestScope() и т. Д., Который звучит так, будто он должен делать трюк. Похоже, что это больше проблема с ninject (или как вы его используете), чем NHibernate. –

+0

Возможно, вы не настроили NInject правильно для MVC? http://stackoverflow.com/questions/24928070/asp-net-mvc-ninject-inrequestscope –

+0

У меня есть это правильно. Я использую NInject.MVC5 и вводя их в правильные контроллеры. Кажется, что проблема состоит в том, что есть два запроса на один и тот же сеанс. Так или иначе, возможно, придется подождать, пока соединение не будет закрыто. Но я не уверен. Я просто не могу поверить, что это так сложно. – NeoSketo

ответ

1

я, наконец, понял это. Большое спасибо @Oskar Berggren за то, что он хотя бы жаждет понимания моей дилеммы.

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

здесь, где я связывание открытой сессии для ContentService:

Bind<IContentService>().To<ContentService>().InRequestScope(); 
     Bind<ISession>() 
      .ToMethod(
       context => 
        context.Kernel.Get<IMasterSessionSource>() 
         .ExposeConfiguration() 
         .BuildSessionFactory() 
         .OpenSession() 
      ) 
      .WhenInjectedInto<IContentService>() 
      .InRequestScope(); 

Вот где я зову ту же сессию в ContentService

public class ContentService : IContentService 
    { 
     private readonly ISession _session; 

     public ContentService(ISession session) 
     { 
      _session = session; 
     } 

     public IQueryable<Question> Questions 
     { 
      get { return _session.Query<Question>(); } 
     } 
    } 

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

public class DetailsService : IDetailsService 
    { 
     private readonly IContentService _contentService; //BAD 


     public GeneralService(IContentService contentService) 
     { 
      _contentService = contentService; //BAD 
     } 

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

так я создал обязательные для DetailService со своей сессии, как так ....

Bind<IDetailsService>() 
       .To<DetailsService>() 
       .InRequestScope(); 

      Bind<ISession>() 
       .ToMethod(
        context => 
        { 
         var lockObject = new object(); 

         lock (lockObject) 
         { 
          return context.Kernel.Get<IMasterSessionSource>() 
           .ExposeConfiguration() 
           .BuildSessionFactory() 
           .OpenSession(); 
         } 
        } 
       ) 
       .WhenInjectedInto<IDetailsService>() 
       .InRequestScope(); 

И вместо вызова _contentService в этой службе я добавил сессию его жома

private readonly ISession Session; 

    public DetailsService(ISession session) 
    { 
     Session = session; 
    } 

затем просто запускает запросы напрямую с помощью Session.Query();

no more Сессия закрыта ошибками, не более ошибок DataReader и, наконец, рабочим продуктом.

0

Я незнаком с Ninject, который я подозреваемый вовлечен в проблему здесь.

Если вы не можете понять, как сделать, чтобы справиться с их должным образом, вы можете взглянуть на собственную обработку NHibernate в контекстных сессий: http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session

+0

Так получается, что его не сессий, это проблема ... MySQL, похоже, преждевременно закрывает сессию на других потоках. Но я до сих пор не знаю, почему и не могу найти решение для этого в любом месте. – NeoSketo