Base solution for your next web application
Open Closed

UnitOfWorkManager.Current.Completed running too soon #1075


User avatar
0
colinplater created

I am working on a website built using ASP.Net Boilerplate. I have a service containing a method, which adds a candidate to the database and then triggers an event. During the event I need to update the candidate, but I am finding that when that code runs it hasn't yet been added to the database. Here is my code:

[AbpAuthorize(RecruitmentPermissions.Recruitment_Candidates_Create)]
        protected virtual async Task CreateCandidateAsync(CandidateEditDto input, bool suppressEvents = false)
        {
            var candidate = input.MapTo<Candidate>();
            candidate.Id = Guid.NewGuid();

            if (candidate.User.TenantId == null)
            {
                Abp.Authorization.Users.UserRole userRole = new Abp.Authorization.Users.UserRole()
                {
                    RoleId = 3
                };

                candidate.User.TenantId = AbpSession.TenantId;

                candidate.User.Name = input.FirstName;
                candidate.User.Surname = input.Surname;
                candidate.User.UserName = input.Username ?? input.EmailAddress;
                candidate.User.Password = new PasswordHasher().HashPassword(input.Password);
                candidate.User.IsActive = true;
                candidate.User.EmailAddress = input.EmailAddress;
                candidate.User.Roles = new List<Abp.Authorization.Users.UserRole>()
                {
                    userRole
                };
                candidate.User.CreatorUserId = AbpSession.UserId;
            }

            // wait for insertion before firing event
            _unitOfWorkManager.Current.Completed += (sender, args) =>
            {
                if (!suppressEvents)
                    EventBus.Trigger(new InsertCandidateEventData { candidate = candidate });
            };

            await _candidateRepository.InsertAsync(candidate);

        }

I have tried using UnitOfWorkManager.Current.Completed, as the documentation suggests that any code inside the { } will be fired after insert has completed - but this is not the case. I have also tried using UnitOfWorkManager.Current.SaveChanges, to force the candidate to be added to the database before firing the event, but again that makes no difference.

I am quite new to the asp.net boilerplate, so any suggestions anyone might have would be greatly appreciated. Thanks


2 Answer(s)
  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    How did you understand that it's not saved to database? You may share the event handler.

  • User Avatar
    0
    colinplater created

    Hi Hikalkan. It looks like the InsertAsync is locking the database table until CreateCandidateAsync has fully completed, which means when the event tries to update the candidate it can't find it. A colleague suggested changing

    _unitOfWorkManager.Current.Completed
    

    to

    _unitOfWorkManager.Current.Disposed
    

    This ensures the event doesn't fire until after the candidate has been added to the database, but also means there is an error when attempting to update the candidate because the UserManagerProxy has been disposed of.

    Is there a way I can recreate the UserManagerProxy, or stop it from being disposed of in the first place?