Releasing ObjectContext while using StructureMap

1.1k views Asked by At

I've been using StructureMap to inject ObjectContext (entities) into my repositories along with lazy-loaded POCO classes. This is my Structuremap registration.

 For<WebEntities>().LifecycleIs(new HybridLifecycle()).Use(()=>new WebEntities());

I have defined Partial classes against my POCO classes to retrieve info that is not defined in my EDMX schema. e.g. Community.FloorPlanImages would be a getter which filters only the floor plan images from all available Images. Worked pretty well until I started to optimize my queries. Using EFProf, I found out that none of my connections were being closed. I could not use an 'using' statement since I'm injecting the ObjectContext itself into my repository. So, I added the following in my Application_EndRequest().

ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();

This works too as long as I don't access anything on my Partial POCOs. I think StructureMap is closing the connection before we get to the Partial. I'm presented with the following error.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

Any ideas to get around this?

UPDATE - Here's the stack trace

ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.] System.Data.Objects.ObjectContext.EnsureConnection() +8550458 System.Data.Objects.ObjectQuery1.GetResults(Nullable1 forMergeOption) +46
System.Data.Objects.ObjectQuery1.Execute(MergeOption mergeOption) +31
System.Data.Objects.DataClasses.EntityCollection
1.Load(List1 collection, MergeOption mergeOption) +243 System.Data.Objects.DataClasses.EntityCollection1.Load(MergeOption mergeOption) +25
System.Data.Objects.DataClasses.RelatedEnd.Load() +37 System.Data.Objects.DataClasses.RelatedEnd.DeferredLoad() +8032198 System.Data.Objects.Internal.LazyLoadBehavior.LoadProperty(TItem propertyValue, String relationshipName, String targetRoleName, Boolean mustBeNull, Object wrapperObject) +85
System.Data.Objects.Internal.<>c_DisplayClass72.<GetInterceptorDelegate>b__1(TProxy proxy, TItem item) +101
System.Data.Entity.DynamicProxies.Community_39641A615E1AD4E19D637735C7A1EBEE61BF70BF579CDD4EBB0267E6636BEC62.get_Videos() +55 Rdx.Web.UI.AppCode.Controllers.CDController.GetCDModel(SearchParams searchParams, Int32 page, Boolean isSorting) in D:\Solutions\RDX\Rdx.Mvc\src\app\Rdx.Web.UI\AppCode\Controllers\CDController.cs:365 Rdx.Web.UI.AppCode.Controllers.CDController.Show(Int32 cid, Int32 bid) in D:\Solutions\RDX\Rdx.Mvc\src\app\Rdx.Web.UI\AppCode\Controllers\CDController.cs:70 lambda_method(Closure , ControllerBase , Object[] ) +145
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary
2 parameters) +208
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +27
System.Web.Mvc.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12() +55 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func
1 continuation) +263 System.Web.Mvc.<>c
_DisplayClass17.b_14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>c_DisplayClass17.b_14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func1 continuation) +263 System.Web.Mvc.<>c_DisplayClass17.b_14() +19 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor, IDictionary2 parameters) +191
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343 System.Web.Mvc.Controller.ExecuteCore() +116 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c
_DisplayClassb.b_5() +37 System.Web.Mvc.Async.<>c_DisplayClass1.b_0() +21 System.Web.Mvc.Async.<>c_DisplayClass81.<BeginSynchronous>b__7(IAsyncResult _) +12 System.Web.Mvc.Async.WrappedAsyncResult1.End() +62 System.Web.Mvc.<>c_DisplayClasse.b_d() +50 System.Web.Mvc.SecurityUtil.b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184

**UPDATE 2: My Application_EndRequest is getting hit twice. What might cause that to happen? **

STACK on first hit.

Nhs.Web.UI.DLL!Nhs.Web.UI.Global.Application_EndRequest(object sender = {ASP.global_asax}, System.EventArgs e = {System.EventArgs}) Line 58 C# System.Web.dll!System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x95 bytes
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.SyncEventExecutionStep}, ref bool completedSynchronously = true) + 0x4c bytes
System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(System.Exception error) + 0x13e bytes
System.Web.dll!System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object extraData) + 0xad bytes
System.Web.dll!System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest wr = {System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6}) + 0x1a2 bytes
System.Web.dll!System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest wr) + 0x7d bytes
System.Web.dll!System.Web.Hosting.ISAPIRuntime.ProcessRequest(System.IntPtr ecb, int iWRType) + 0xfd bytes
[Appdomain Transition]
[Native to Managed Transition]

STACK on second hit

Nhs.Web.UI.DLL!Nhs.Web.UI.Global.Application_EndRequest(object sender = {ASP.global_asax}, System.EventArgs e = {System.EventArgs}) Line 58 C# System.Web.dll!System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() + 0x95 bytes
System.Web.dll!System.Web.HttpApplication.ExecuteStep(System.Web.HttpApplication.IExecutionStep step = {System.Web.HttpApplication.SyncEventExecutionStep}, ref bool completedSynchronously = true) + 0x4c bytes
System.Web.dll!System.Web.HttpApplication.ApplicationStepManager.ResumeSteps(System.Exception error) + 0x13e bytes
System.Web.dll!System.Web.HttpApplication.ResumeStepsWaitCallback(object error) + 0x1e bytes
mscorlib.dll!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(object state) + 0x2d bytes mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes
mscorlib.dll!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() + 0x5a bytes mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() + 0x147 bytes
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() + 0x2d bytes
[Native to Managed Transition]
[Appdomain Transition]
[Native to Managed Transition]

1

There are 1 answers

4
Kim Tranjan On

Try it

For(typeof(WebEntities)).LifecycleIs(InstanceScope.Hybrid);

Global.asax

protected void Application_EndRequest(object sender, EventArgs e) {
    ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}

StructureMap will store the context every time that you do the access

var db = ObjectFactory.GetInstance<WebEntities>();