Коллекция ошибок Autopper была изменена, когда несколько пользователей создают пользователя

Я получаю следующую ошибку, и эта ошибка появляется только тогда, когда несколько пользователей нажимают одну и ту же кнопку. Любая помощь / идеи будут по достоинству оценены:

System.InvalidOperationException: коллекция была изменена; Операция перечисления может не выполняться. Сгенерировано: ср, 10 июня 2015 07:29:06 GMT

AutoMapper.AutoMapperMappingException:

Типы сопоставления: Пользователь -> Пользователь ApplicationSecurityManager.Service.User -> ApplicationSecurityManager.Models.User

Путь назначения: пользователь

Исходное значение: ApplicationSecurityManager.Service.User ---> System.InvalidOperationException: коллекция была изменена; Операция перечисления может не выполняться. в System.Collections.Generic.List1.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, Action1 вариант) в ApplicationSecurityManager.UserManager.LoadUser(имя пользователя в виде строки) в ApplicationSecurityManager.UserManager.get_AuthenticatedUser() в ApplicationSecurityManager.UserManager.IsAuthenticated() в фильтре ApplicationSecurityManager.Inxt. InvokeAuthorizationFilters (ControllerContext controllerContext, IList1 filters, ActionDescriptor actionDescriptor) at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.Begin (обратный вызов AsyncCallback, состояние объекта, время ожидания Int32) в System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](обратный вызов AsyncCallback, состояние объекта, BeginInvokeDelegate beginDelegate, EndInvokeDelegate1 endDelegate, Object tag, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate1 endDelegate, Тег объекта) в System.Web.Mvc.Controller.<> C__DisplayClass1d.b__17(AsyncCallback asyncCallback, Object asyncState) в System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate1 endDelegate, Тег объекта, время ожидания Int32) в System.Web.Mvc.Controller.BeginExecuteCore(обратный вызов AsyncCallback, состояние объекта) в System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate1 endDelegate, тег объекта, тайм-аут Int32) в System.Web.Mvc.Async.AsyncResultWrapper.Begin(обратный вызов AsyncCallback, состояние объекта, BeginInvokeDelegate beginDelegate, конец EndInvokeDelegate endDelegate, тег объекта) в System.Web.Mvc.ExteContext, Обратный вызов AsyncCallback, состояние объекта) в System.Web.Mvc.MvcHandler.<> C__DisplayClass8.b__2(AsyncCallback asyncCallback, объект asyncState) в System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.Begin(AsyncCallback callback, Object state, Int32 timeout) at System.Web.Mvc.Async.AsyncResultWrapper.Begin[TResult](AsyncCallback callback, Object state, BeginInvokeDelegate beginDelegate, EndInvokeDelegate1 endDelegate, тег объекта, тайм-аут Int32) в System.Web.Mvc.Async.AsyncResultWrapper.Begin(обратный вызов AsyncCallback, состояние объекта, BeginInvokeDelegate beginDelegate, конец EndInvokeDelegate endDelegate, тег объекта) в System.Web.McessTexTextBegin.Text.Web.Tec.Begin.tb, Обратный вызов AsyncCallback, состояние объекта) в System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() в System.Web.HttpApplication.ExecuteStep(завершенный шаг IExecutionStep, Boos)

Это конструктор, в котором я думаю, что проблема в посткарте, но при отладке я не получаю сообщение об ошибке.

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)

Отображение зависимостей инъекций:

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 ответа

Решение

Это происходит, когда несколько пользователей изменяют одну и ту же коллекцию user.Groups в методе AfterMap() вашего сопоставления. Чтобы избежать этого, заблокируйте код, который обрабатывает коллекцию. Например:

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

Это довольно распространенная ошибка при изменении коллекции при ее повторении. Возможно, вы что-то оставляете здесь, а мы не видим? Во всяком случае, в коде, который вы предоставили, нет такого сценария из того, что я вижу. Это означает, что вы можете вызывать это в многопоточной среде, а коллекция изменяется в каком-то другом потоке.

Что вы можете попробовать?

Посмотрите на блокировку вашего enumeration таким образом, только один поток за один раз может быть доступен. Возможно, к нему обращаются несколько раз, когда пользователь нажимает на кнопку.

Вот хорошая ссылка, чтобы помочь вам: http://weblogs.asp.net/leftslipper/mvc-locking-the-routecollection

Другие вопросы по тегам