Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

EF7 Interleaving guard and ViewComponents #3797

Closed
balneaves opened this issue Dec 20, 2015 · 1 comment
Closed

EF7 Interleaving guard and ViewComponents #3797

balneaves opened this issue Dec 20, 2015 · 1 comment

Comments

@balneaves
Copy link

I updated to the latest rc2/unstable packages (mvc 6.0.0-rc2-16683, ef 7.0.0-rc2-16583), and previously working code now throws the following error :
NotSupportedException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe. Microsoft.Data.Entity.Internal.ConcurrencyDetector.EnterCriticalSection()

Not sure if this is an issue with my code, with EF or with MVC, but it comes when using async ViewComponents:

  1. Page that loads multiple of the same ViewComponent @await Component.InvokeAsync("SomeViewComponent", Model, stage)
  2. Both View/Controller and ViewComponent utilize the same Service (although injected through constructors rather than passed as params)
  3. EF7 is injected using the standard services.AddEntityFramework()
  4. ViewComponent calls a service to do the EF query (service injected as AddScoped)
  5. None of my code/queries call any Async methods (other than the Mvc sucks bro #1 above)
  6. Error is thrown on calling `.ToList()' on the query.
  7. Only occurs if the query returns results
  8. Only occurs if more than 1 ViewComponent is called (that uses the same data)... if I hardcode the foreach in my View to only render the first element it all works
  9. No writing done, only reads

Related to : dotnet/efcore#3291

Full stack:

System.NotSupportedException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
   at Microsoft.Data.Entity.Internal.ConcurrencyDetector.EnterCriticalSection()
   at Microsoft.Data.Entity.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.Contains[TSource](IEnumerable`1 source, TSource value, IEqualityComparer`1 comparer)
   at lambda_method(Closure , TransparentIdentifier`2 )
   at System.Linq.Enumerable.<>c__DisplayClass6_0`1.<CombinePredicates>b__0(TSource x)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at Microsoft.Data.Entity.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__15`2.MoveNext()
   at Microsoft.Data.Entity.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()
   at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at MyProject.Services.PipelineService.GetValidVersionsForStage(PipelineStage stage, Component component, Int32 max)
   at MyProject.ViewComponents.PipelineApprovalActionViewComponent.Invoke(Component component, PipelineStage pipelineStage)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNet.Mvc.ViewComponents.DefaultViewComponentInvoker.InvokeSyncCore(MethodInfo method, ViewComponentContext context)
   at Microsoft.AspNet.Mvc.ViewComponents.DefaultViewComponentInvoker.<InvokeAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNet.Mvc.ViewComponents.DefaultViewComponentHelper.<InvokeAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at CallSite.Target(Closure , CallSite , Object )
   at Asp.ASPV__Views_Component_Index_cshtml.<ExecuteAsync>d__22.MoveNext()```
@balneaves
Copy link
Author

I solved this by forcing my services to return/use lists rather than queries when using async viewcomponents

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant