Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I have a bug deleting an entity and soft delete does not seem to be applied. instead of marking the deleted field, it does hard delete #19721

Open
ktngoykalolo opened this issue May 6, 2024 · 9 comments

Comments

@ktngoykalolo
Copy link

ktngoykalolo commented May 6, 2024

  • ABP version 8.
  • MVC single-Layer template
  • EfCore
  • when deleting an entity, I have the below exception being thrown by the Repository. It seems that the DBContext is being called twice.
  • it also seems that the soft delete does not work at all
  • System.InvalidOperationException
    HResult=0x80131509
    Message=A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.
    Source=Microsoft.EntityFrameworkCore
    StackTrace:
    at Microsoft.EntityFrameworkCore.Infrastructure.Internal.ConcurrencyDetector.EnterCriticalSection()
    at Microsoft.EntityFrameworkCore.Query.Internal.SplitQueryingEnumerable1.Enumerator.MoveNext() at System.Linq.Enumerable.TryGetSingle[TSource](IEnumerable1 source, Boolean& found)
    at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
    at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
    at Microsoft.EntityFrameworkCore.Internal.EntityFinder1.GetDatabaseValues(InternalEntityEntry entry) at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.GetDatabaseValues() at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.Reload() at Volo.Abp.EntityFrameworkCore.AbpDbContext1.ApplyAbpConceptsForDeletedEntity(EntityEntry entry)
    at Volo.Abp.EntityFrameworkCore.AbpDbContext1.PublishEventsForTrackedEntity(EntityEntry entry) at Volo.Abp.EntityFrameworkCore.AbpDbContext1.ChangeTracker_StateChanged(Object sender, EntityStateChangedEventArgs e)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.OnStateChanged(InternalEntityEntry internalEntityEntry, EntityState oldState)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.FireStateChanged(EntityState oldState)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
    at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable1 forceStateWhenUnknownKey, Nullable1 fallbackState)
    at Microsoft.EntityFrameworkCore.DbContext.RemoveRange(IEnumerable1 entities) at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository2.d__27.MoveNext()
    at Volo.Abp.Domain.Repositories.EntityFrameworkCore.EfCoreRepository2.<DeleteAsync>d__36.MoveNext() at Castle.DynamicProxy.AsyncInterceptorBase.<ProceedAsynchronous>d__13.MoveNext() at Volo.Abp.Castle.DynamicProxy.CastleAbpMethodInvocationAdapter.<ProceedAsync>d__7.MoveNext() at Volo.Abp.Uow.UnitOfWorkInterceptor.<InterceptAsync>d__2.MoveNext() at Volo.Abp.Castle.DynamicProxy.CastleAsyncAbpInterceptorAdapter1.d__2.MoveNext()
    at Komatel.Perenco.TrackingApp.Services.CostCenterAppService.d__9.MoveNext() in C:\Users\ktngo\OneDrive\Documents\Visual Studio 2022\Komatel.Perenco.TrackingApp\Komatel.Perenco.TrackingApp\Komatel.Perenco.TrackingApp\Services\CostCenterAppService.cs:line 127
    at System.Threading.Tasks.Task.<>c.b__128_1(Object state)
    at System.Threading.QueueUserWorkItemCallback.Execute()
    at System.Threading.ThreadPoolWorkQueue.Dispatch()
    at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
@ktngoykalolo ktngoykalolo changed the title I have a bug deleting an entity. soft delete does not seem to be applied I have a bug deleting an entity and soft delete does not seem to be applied. instead of marking the deleted field, it does hard delete May 6, 2024
@ktngoykalolo
Copy link
Author

ktngoykalolo commented May 6, 2024

using Komatel.Perenco.TrackingApp.Entities;
using Komatel.Perenco.TrackingApp.Services.Dtos;
using Komatel.Perenco.TrackingApp.Services.Interfaces;
using Volo.Abp.Domain.Repositories;
using Komatel.Perenco.TrackingApp.ObjectMapping;
using Volo.Abp.Application.Dtos;
using Komatel.Perenco.TrackingApp.Data;
using Komatel.Perenco.TrackingApp.Entities.Interfaces;



namespace Komatel.Perenco.TrackingApp.Services
{
    public class CostCenterAppService : TrackingAppAppService, ICostCenterAppService
    {

        private readonly ICostCenterRepository _costCenterRepository;
        private readonly IRepository<ServiceCostCenter> _serviceCostCenterRepository;




        public CostCenterAppService()
        { }
        public CostCenterAppService(ICostCenterRepository CostCenterRepo, IRepository<ServiceCostCenter> serviceCostCenterRepo)
        {
            _costCenterRepository = CostCenterRepo;
            _serviceCostCenterRepository = serviceCostCenterRepo;
        }



        //public async Task<List<CostCenterDto>> GetCostCentersAsync()
        //{
        //    var costCenters = await _costCenterRepository.GetListAsync();

        //    var dtos = new List<CostCenterDto>();

        //    dtos = ObjectMapper.Map<List<CostCenter>, List<CostCenterDto>>(costCenters, dtos);

        //    return dtos;
        //}

        public async Task<PagedResultDto<CostCenterDto>> GetCostCentersAsync(GetCostCenterListDto input)
        {
            var costCenters = await _costCenterRepository.GetListAsync();

            var dtos = new List<CostCenterDto>();

            dtos = ObjectMapper.Map<List<CostCenter>, List<CostCenterDto>>(costCenters, dtos);


            if (input.Sorting.IsNullOrWhiteSpace())
            {
                input.Sorting = nameof(CostCenter.Name);
            }

            var costs = await _costCenterRepository.GetListAsync(
                input.SkipCount,
                input.MaxResultCount,
                input.Sorting,
                input.Filter
            );

            var totalCount = input.Filter == null
                ? await _costCenterRepository.CountAsync()
                : await _costCenterRepository.CountAsync(
                    cost => cost.Name.Contains(input.Filter));

            return new PagedResultDto<CostCenterDto>(
                totalCount,
                ObjectMapper.Map<List<CostCenter>, List<CostCenterDto>>(costs)
            );
        }



        public async Task<CostCenterDto> GetCostCenter(Guid Id)
        {
            var costCenters = await _costCenterRepository.GetAsync(Id);


           
           var dto = ObjectMapper.Map<CostCenter, CostCenterDto>(costCenters);

            return dto;

        }

        public async Task<List<ServiceCostCenterDto>> GetCostCentersAndServices(Guid costcenterid)
        {
            var serviceCostCenters = await _serviceCostCenterRepository.GetListAsync(c => c.CostCenterId == costcenterid);

            var dtos = new List<ServiceCostCenterDto>();

            dtos = ObjectMapper.Map<List<ServiceCostCenter>, List<ServiceCostCenterDto>>(serviceCostCenters, dtos);

            return dtos;
        }

        public async void CreateCostCenterAsync(CostCenterDto dto)
        {

            var costcenter = ObjectMapper.Map<CostCenterDto, CostCenter>(dto);

           await _costCenterRepository.InsertAsync(costcenter);

           

        }


        public async void UpdateCostCenter(CostCenterDto dto)
        {

            var costcenter = ObjectMapper.Map<CostCenterDto, CostCenter>(dto);

            await _costCenterRepository.UpdateAsync(costcenter);


        }

        public async void DeleteCostCenter(Guid id)
        {

          
            await _costCenterRepository.DeleteAsync(x => x.Id == id);


        }

     

        Task<List<CostCenterDto>> ICostCenterAppService.GetCostCentersAsync()
        {
            throw new NotImplementedException();
        }
    }
}

@ktngoykalolo
Copy link
Author

ktngoykalolo commented May 6, 2024

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Komatel.Perenco.TrackingApp.Entities;
using Komatel.Perenco.TrackingApp.Entities.Interfaces;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;


namespace Komatel.Perenco.TrackingApp.Data
{
    public class EfCoreCostCenterRepository : EfCoreRepository<TrackingAppDbContext, CostCenter, Guid>, ICostCenterRepository
    {
        public EfCoreCostCenterRepository(IDbContextProvider<TrackingAppDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }

        public async Task<List<CostCenter>> GetListAsync(int skipCount, int maxResultCount, string sorting, string filter)
        {
            var dbSet = await GetDbSetAsync();
            return await dbSet
                .WhereIf(
                    !filter.IsNullOrWhiteSpace(),
                    cost => cost.Name.Contains(filter)
                 )
                .OrderBy(sorting)
                .Skip(skipCount)
                .Take(maxResultCount)
                .ToListAsync();
        }
    }
}

@maliming
Copy link
Member

maliming commented May 7, 2024

hi

Please change all return type from async void to async Task .

@ktngoykalolo
Copy link
Author

hi @maliming ,
I need to change on the repositories and the Appservice ?

@maliming
Copy link
Member

maliming commented May 8, 2024

hi

You have to change all the code like this. Never use async void as the return type for async methods.

@ktngoykalolo
Copy link
Author

noted but now I am getting the following error with update method.
"The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning."

@maliming
Copy link
Member

maliming commented May 9, 2024

public async Task UpdateCostCenter(CostCenterDto dto)
{
    var costcenter = _costCenterRepository.GetAsync(dto.Id);
    ObjectMapper.Map<CostCenterDto, CostCenter>(dto, costcenter);
    await _costCenterRepository.UpdateAsync(costcenter);
}

@ktngoykalolo
Copy link
Author

hello,
will try the changes and advise. I suspect I was not properly mapping the objects with automapper.

@maliming
Copy link
Member

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

No branches or pull requests

2 participants