当多个用户创建用户时,会修改automapper错误集合

时间:2015-06-10 08:45:52

标签: asp.net-mvc vb.net dependency-injection automapper-3

我收到以下错误,只有当多个用户点击同一个按钮时才会出现此错误。任何帮助/想法将非常感激:

  

System.InvalidOperationException:修改了集合;列举   操作可能无法执行。生成:2015年6月10日星期三07:29:06 GMT

     

AutoMapper.AutoMapperMappingException:

     

映射类型:用户 - > User ApplicationSecurityManager.Service.User - >   ApplicationSecurityManager.Models.User

     

目的地路径:用户

     

来源价值:ApplicationSecurityManager.Service.User ---&gt;   System.InvalidOperationException:集合已被修改;列举   操作可能无法执行。在   System.Collections.Generic.List 1.Enumerator.MoveNextRare() at AutoMapper.TypeMap.<get_AfterMap>b__1(Object src, Object dest) at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) --- End of inner exception stack trace --- at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context) at AutoMapper.MappingEngine.Map[TDestination](Object source, Action 1 opts)at   ApplicationSecurityManager.UserManager.LoadUser(String username)at   ApplicationSecurityManager.UserManager.get_AuthenticatedUser()at   ApplicationSecurityManager.UserManager.IsAuthenticated()at   ApplicationSecurityManager.Infrastructure.ApplicationSecurityAttribute.OnAuthorization(AuthorizationContext   filterContext)at   System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext   controllerContext,IList 1 filters, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback   回调,对象状态,Int32超时)at   System.Web.Mvc.Async.AsyncResultWrapper.Begin [TResult](的AsyncCallback   回调,对象状态,BeginInvokeDelegate beginDelegate,   EndInvokeDelegate 1 endDelegate, Object tag, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate,Object tag)at   System.Web.Mvc.Controller&LT;&GT; c__DisplayClass1d.b__17(的AsyncCallback   asyncCallback,Object asyncState)at   System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate,Object tag,Int32 timeout)at   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback回调,   对象状态)   System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate,Object tag,Int32 timeout)at   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback回调,   对象状态,BeginInvokeDelegate beginDelegate,EndInvokeDelegate   endDelegate,Object tag)at   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext,   AsyncCallback回调,对象状态)   System.Web.Mvc.MvcHandler&LT;&GT; c__DisplayClass8.b__2(的AsyncCallback   asyncCallback,Object asyncState)at   System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult 1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate 1 endDelegate,Object tag,Int32 timeout)at   System.Web.Mvc.Async.AsyncResultWrapper.Begin(AsyncCallback回调,   对象状态,BeginInvokeDelegate beginDelegate,EndInvokeDelegate   endDelegate,Object tag)at   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase   httpContext,AsyncCallback回调,对象状态)at   System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()   在System.Web.HttpApplication.ExecuteStep(IExecutionStep步骤,   布尔和放大器; completedSynchronously)

这是构造函数,我认为aftermap是问题但是在调试时我没有收到错误。

Public Sub New(environmentCode As String, applicationCode As String)
    MyBase.New(environmentCode, applicationCode)

    SOBaseUrl = System.Configuration.ConfigurationManager.AppSettings(Enums.AppSettingKeys.SOBaseUrl.ToString())
    If Not String.IsNullOrEmpty(SOBaseUrl) Then
        SOBaseUrl = SOBaseUrl.TrimEnd("/")
    End If

    'Setup mapping.
    Mapper.CreateMap(Of Service.User, Models.User)() _
        .ForMember(Function(dest As Models.User) dest.ENumber, Sub(opt) opt.MapFrom(Function(src As Service.User) src.INumber)) _
        .AfterMap(Sub(src As Service.User, dest As Models.User)

            dest.Groups = New List(Of String)

            Using service = ApplicationSecurityManager.Service.Factory.GetService()

                Dim applicationPermissions = service.LoadPermissionsForUser(dest.Username, MyBase.EnvironmentCode)

                If (Not applicationPermissions Is Nothing AndAlso applicationPermissions.Any(Function(x) x.Code = MyBase.ApplicationCode)) Then

                    dest.Groups = applicationPermissions.Single(Function(x) x.Code = MyBase.ApplicationCode).GroupNames.ToList()

                End If

            End Using

        End Sub)

Depenendency Injection Mapping:

container.RegisterType(Of IUserManager, UserManager)(New PerThreadLifetimeManager(),
    New InjectionConstructor(
      ConfigurationManager.AppSettings(Common.Enums.AppSettingKeys.Environment.ToString()),
      ConfigurationManager.AppSettings(Common.Enums.AppSettingKeys.ApplicationCode.ToString()))
    )

saveUserResponse中,错误将被抛出。

 Public Function Create(user As Common.Models.User, approve As Boolean) As SO.Common.Models.User Implements IUserProvider.Save

    Dim saveUserResponse = UserManager.SaveUser(Mapper.Map(Of ApplicationSecurityManager.Service.User)(user))

    If Not String.IsNullOrEmpty(saveUserResponse.ErrorMessage) Then

        'The Security system returned an error.

        Throw New Exception("Security Service returned error: " & saveUserResponse.ErrorMessage)

    End If

    'Return the username.
    Return Mapper.Map(Of Common.Models.User)(saveUserResponse.User)

End Function

2 个答案:

答案 0 :(得分:1)

This is pretty common mistake modifying a collection while iterating it. Is it possible you are leaving something out here we can't see? Anyway's in the code that you have provided there is not any such scenario from what I can see. This means that you might be calling this in a multi-threaded environment and the collection is being modified in some other thread.

What can you try?

Look into locking your enumeration so only one thread at a time can be accessed. It's possible that it's being accessed multiple time's when user's are clicking on the button.

Here's a good link to help you out: http://weblogs.asp.net/leftslipper/mvc-locking-the-routecollection

答案 1 :(得分:1)

当多个用户在映射的AfterMap()方法中修改相同的user.Groups集合时,会导致这种情况。要避免这种情况,请锁定正在处理集合的代码。例如:

'class level object
private object _myLock = New object()

'Setup mapping.
Mapper.CreateMap(Of Service.User, Models.User)() _
    .ForMember(Function(dest As Models.User) dest.ENumber, Sub(opt) opt.MapFrom(Function(src As Service.User) src.INumber)) _
    .AfterMap(Sub(src As Service.User, dest As Models.User)
                  SyncLock _myLock
                      dest.Groups = New List(Of String)

                      Using service = ApplicationSecurityManager.Service.Factory.GetService()

                          Dim applicationPermissions = service.LoadPermissionsForUser(dest.Username, MyBase.EnvironmentCode)

                          If (Not applicationPermissions Is Nothing AndAlso applicationPermissions.Any(Function(x) x.Code = MyBase.ApplicationCode)) Then

                              dest.Groups = applicationPermissions.Single(Function(x) x.Code = MyBase.ApplicationCode).GroupNames.ToList()

                          End If

                      End Using
                  End SyncLock

              End Sub)