2016-07-26 147 views
5

我在一個MVC C#應用程序與MySQL使用NHibernate。我試圖讓多個用戶訪問會話。我一直在使用.InRequestScope()在我的會話中,但我仍然得到:會話已關閉對象名稱:'ISession'。在NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() - 如何阻止會話過早關閉

System.ObjectDisposedException:Session is closed!對象名稱:'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>(); } 
     } 
    } 

DetailsS​​ervice

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; 
     } 
} 

控制器

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) 
} 

因此,對於訪問該頁面的單個用戶。一切正常。但是,當複式用戶visist在同一頁各獲得錯誤:

{「已經有與此連接必須先關閉相關聯的打開的DataReader。」} {「目前已經與相關聯的打開的DataReader 「 {」數據閱讀器中沒有當前查詢「} {」數據閱讀器中沒有當前查詢「} {」已經有一個打開的DataReader與此連接相關聯,必須先關閉它「} {」Session is closed!\ r \ n對象名稱:'ISession'。「}

我已經添加了InRequestScope。我甚至添加了這個實現: NHibernate, and odd "Session is Closed!" errors

但我仍然得到Sessions關閉!錯誤。如果會話關閉,我甚至嘗試創建一個新的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
c:\ Users \ wd \ Desktop \ master \ Gcus.PublicGeneralSite.Data中的Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsS​​ervice.FindItems(字符串 項目,字符串控制器) 。 Core \ Service \ General \ DetailsS​​ervice.cs:724 gcus.Com.Web.Controllers.CoursesController.Details(String category, String item)in c:\ Users \ wd \ Desktop \ master \ Gcus.Com.Web \控制器\ CoursesController.cs:213 lambda_method(封閉,ControllerBase,對象[])36​​6
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase 控制器,對象[]參數)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, 對象標記)+136
系統.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 .PrappedAsyncVoid 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, 對象標籤)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一步,布爾& completedSynchronously)+137

+0

對於多個併發會話,NHibernate肯定沒有問題。事實上,它旨在處理這種情況。但它不能處理對_single_會話的併發訪問。會話不是線程安全的。你似乎意識到這一點,因爲你談論的InRequestScope()等,這聽起來像它應該做的伎倆。看起來這對於ninject(或者你如何使用它)比NHibernate更有問題。 –

+0

也許你還沒有爲MVC正確設置NInject? 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 
     } 

這不是線程安全的其他服務相同的會話,因爲一個開放的會話得到重用。 每個服務都應該有自己的會話。

,所以我創造了該服務調用_contentService的,象這樣它自己的會話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(); 

,而是我加入了會議,其大蟒

private readonly ISession Session; 

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

那麼只需使用Session.Query()直接運行查詢;

沒有更多的會話是關閉錯誤,沒有更多的DataReader錯誤,最後一個工作產品。

0

我不熟悉ninject,我嫌疑人在這裏涉及這個問題。

如果你不能弄清楚如何使正確處理會話,你可以看看NHibernate的自己處理情境會話:http://nhibernate.info/doc/nhibernate-reference/architecture.html#architecture-current-session

+0

因此事實證明,它並不是這就是問題所在...... MySQL似乎在其他線程上過早地關閉了會話,但我仍然不知道爲什麼,也無法找到解決此問題的任何地方。 – NeoSketo