You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 6.0 + ABP 6.0中同一函数内更新父表、关联表及子表的异常问题

Hey there, let's break down the issues you're facing with your ABP 6.0 update logic and fix them one by one:

Core Issues Explained

  1. BiometricInfoBase not updating: When you map the input directly to a new DarbanPrisonerEntry instance, that entity is detached from the EF Core context. ABP's UpdateAsync only updates the entity itself, not its navigation properties. Your standalone Biometric update failed because you were trying to update a detached entity (EF didn't recognize it as an existing record, so it tried to insert a new one instead).
  2. DabanPrisonerUnderSections duplicating: The mapped UnderSections list contains new, untracked objects. EF Core treats these as brand new records instead of replacing or updating existing associations.

Fixed Update Method Code

Here's the revised CreateUpdateDarbanPrisonerEntry method that addresses all these problems:

public async Task<CreateEditDarbanPrisonerEntryOutputDto> CreateUpdateDarbanPrisonerEntry(CreateEditDarbanPrisonerEntryInputDto input)
{
    var response = new CreateEditDarbanPrisonerEntryOutputDto();
    try
    {
        using (_unitOfWorkManager.Current.SetTenantId(AbpSession.TenantId.GetValueOrDefault()))
        {
            if (AbpSession.UserId == null)
            {
                response.IsSuccessful = false;
                throw new UserFriendlyException("User not logged in");
            }

            // Fetch the existing tracked entity with all related data
            var existingDarban = await _darbanEntryRepo.GetAsync(
                input.Data.Id,
                include: x => x.Include(d => d.Biometric).Include(d => d.UnderSections)
            );

            // Map core parent entity properties (excluding navigation properties we'll handle manually)
            _objectMapper.Map(input.Data, existingDarban);

            // Update associated BiometricInfoBase
            if (input.Data.Biometric != null)
            {
                if (existingDarban.Biometric != null)
                {
                    // Map changes to the tracked Biometric entity (EF will detect and update it)
                    _objectMapper.Map(input.Data.Biometric, existingDarban.Biometric);
                }
                else
                {
                    // Fallback: if Biometric didn't exist before, create and attach it
                    var newBiometric = _objectMapper.Map<BiometricInfoBase>(input.Data.Biometric);
                    existingDarban.Biometric = newBiometric;
                    await _biometricBaseRepo.InsertAsync(newBiometric);
                }
            }

            // Handle child sections (full replacement - adjust if partial updates are needed)
            // Step 1: Remove all existing sections
            foreach (var existingSection in existingDarban.UnderSections.ToList())
            {
                await _dabanPrisonerUnderSectionsRepo.DeleteAsync(existingSection);
            }
            // Step 2: Add new sections from input
            foreach (var sectionDto in input.Data.UnderSections)
            {
                var newSection = _objectMapper.Map<DabanPrisonerUnderSections>(sectionDto);
                newSection.DarbanPrisonerEntryId = existingDarban.Id; // Ensure foreign key is set correctly
                existingDarban.UnderSections.Add(newSection);
                await _dabanPrisonerUnderSectionsRepo.InsertAsync(newSection);
            }

            // Save all changes (ABP will handle tracking automatically since we're using existing entities)
            await _darbanEntryRepo.UpdateAsync(existingDarban);
            await CurrentUnitOfWork.SaveChangesAsync();

            response.IsSuccessful = true;
            response.Data = _objectMapper.Map<DarbanPrisonerEntryDto>(existingDarban);
        }
    }
    catch (Exception ex)
    {
        response.IsSuccessful = false;
        throw new UserFriendlyException(ex.InnerException?.Message ?? ex.Message);
    }
    return response;
}

Key Fixes Breakdown

  • Tracked Entities: By fetching the existing entity with Include for navigation properties, EF Core keeps track of all related objects. This lets it automatically detect changes when you map input values to them.
  • Biometric Update: Instead of creating a new detached Biometric entity, we modify the tracked one that's already linked to the parent. EF will mark it as modified and update it during save.
  • Child Sections Handling: We fully replace existing sections with the input's new list (delete old, add new). If you need partial updates (only modify changed sections), you'd need to compare input sections with existing ones to determine add/update/delete actions.
  • Unit of Work: All operations run in the same unit of work, ensuring atomicity (either all changes save, or none do).

内容的提问来源于stack exchange,提问作者usama rahman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 19:14:10