I am using NHibernate in an MVC C# application with MySQL. I am trying to have multiple users access the session. I have been using .InRequestScope()
on my session but i am still getting:
System.ObjectDisposedException: Session is closed! Object name: 'ISession'. at NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() *
...or DataReader errors when i have my colleagues all navigate to the same page that accesses a Service at the same time.
My IMasterSessionSource injection
Bind<IMasterSessionSource>().To<GeneralMasterSessionSource()
.InRequestScope();
My IContentService is where my mappings are getting serviced
//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();
};
}
}
}
MODEL
public class HomePageContent
{
public IEnumerable<Question> Questions { get; set; }
}
VIEW
foreach(var question in Model.Questions){
@Html.Raw(question.Question)
}
So for a single user visiting that page. All works fine. But when mutliple users visist the same page each get the errors:
{"There is already an open DataReader associated with this Connection which must be closed first."} {"There is already an open DataReader associated with this Connection which must be closed first."} {"No current query in data reader"} {"No current query in data reader"} {"There is already an open DataReader associated with this Connection which must be closed first."} {"Session is closed!\r\nObject name: 'ISession'."}
I already added InRequestScope. I even added this implementation: NHibernate, and odd "Session is Closed!" errors
but I am still getting Sessions are closed! errors. I even tried to create a new Kernel.Get if the session was closed, but the problem is that the error sometimes occurs even when the session is open. Please help! I am at wits end with this issue, and I can't seem to find the solution anywhere. I almost think it's impossible for NHibernate to handle more than one session at once.
UPDATE
Maybe there's a way to wait for disposed session before opening new?
Stack Trace
[ObjectDisposedException: Session is closed! Object name: 'ISession'.] NHibernate.Impl.AbstractSessionImpl.ErrorIfClosed() +192
NHibernate.Impl.AbstractSessionImpl.CheckAndUpdateSessionStatus() +55 NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression) +171
NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery) +226
NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +80 NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) +74 Remotion.Linq.QueryableBase1.GetEnumerator() +193 System.Collections.Generic.List
1..ctor(IEnumerable1 collection) +432 System.Linq.Enumerable.ToList(IEnumerable
1 source) +70
Gcus.PublicGeneralSite.Data.Core.Service.General.DetailsService.FindItems(String item, String controller) in c:\Users\wd\Desktop\master\Gcus.PublicGeneralSite.Data.Core\Service\General\DetailsService.cs:724 Gcus.Com.Web.Controllers.CoursesController.Details(String category, String item) in c:\Users\wd\Desktop\master\Gcus.Com.Web\Controllers\CoursesController.cs:213 lambda_method(Closure , ControllerBase , Object[] ) +366
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +87
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +603
2 parameters) +93
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary
System.Web.Mvc.Async.ActionInvocation.InvokeSynchronousActionMethod() +97 System.Web.Mvc.Async.AsyncControllerActionInvoker.b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +53
System.Web.Mvc.Async.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) +137
1.End() +187
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +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.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +79
1.End() +187
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +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.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +75
1.End() +176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +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.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +135
1.End() +176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +51
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +66 System.Web.Mvc.Controller.b__15(IAsyncResult asyncResult, Controller controller) +60
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +98
1.End() +176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +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.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +135
1.End() +176
System.Web.Mvc.Async.WrappedAsyncResultBase
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +72
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +51
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +59
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +399 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137
I finally figured it out. Much appreciation to @Oskar Berggren for at least being avid on understanding my dilemma.
The problem was that I, in fact, was sharing one session all along.
here is where i am binding an open session to ContentService:
Bind<IContentService>().To<ContentService>().InRequestScope();
Bind<ISession>()
.ToMethod(
context =>
context.Kernel.Get<IMasterSessionSource>()
.ExposeConfiguration()
.BuildSessionFactory()
.OpenSession()
)
.WhenInjectedInto<IContentService>()
.InRequestScope();
Here is where i am calling the same session in ContentService
public class ContentService : IContentService
{
private readonly ISession _session;
public ContentService(ISession session)
{
_session = session;
}
public IQueryable<Question> Questions
{
get { return _session.Query<Question>(); }
}
}
Here is where the problem is. I am calling the SAME session in another service that is being used elsewhere
public class DetailsService : IDetailsService
{
private readonly IContentService _contentService; //BAD
public GeneralService(IContentService contentService)
{
_contentService = contentService; //BAD
}
This is not thread safe, because that one open session is getting reused. Each service should have its own session.
so i created binding for DetailService with its own session like so....
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();
And instead of calling _contentService in that service i added the session to its constrictor
private readonly ISession Session;
public DetailsService(ISession session)
{
Session = session;
}
then just ran queries directly using Session.Query();
no more Session is closed errors, no more DataReader Errors, and finally a working product.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With