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

ABP Framework 6.0父子实体处理最佳实践及跟踪错误解决咨询

父子实体场景下ABP Framework 6.0的跟踪冲突问题及最佳实践咨询

项目概述

近期基于ABP Framework 6.0开发,创建了DemoApp项目用于复现问题。

领域层实体

Company.cs

public class Company : FullAuditedAggregateRoot<Guid>
{
    public virtual string Code { get; set; }

    public virtual string Name { get; set; }

    public virtual ICollection<Site> Sites { get; set; }
}

Site.cs

public class Site : AuditedEntity<Guid>
{
    protected Site()
    {
    }

    public Site(Guid id) : base(id)
    {
    }

    public virtual Guid CompanyId { get; set; }

    public virtual Company Company { get; set; }

    public virtual string Code { get; set; }

    public virtual string Name { get; set; }
}

注:原Site类继承FullAuditedEntity<Guid>,后改为AuditedEntity<Guid>

应用契约层DTO

  • CompanyDto.cs
  • CreateCompanyDto.cs
  • UpdateCompanyDto.cs
  • SiteOfCompanyDto.cs(关联CompanyDto)
  • SiteOfCreateCompanyDto.cs(关联CreateCompanyDto)
  • SiteOfUpdateCompanyDto.cs(关联UpdateCompanyDto)

应用层服务实现

public class CompanyService : ApplicationService, ICompanyService
{
    private readonly ICompanyRepository _companyRepository;

    public CompanyService(ICompanyRepository companyRepository)
    {
        _companyRepository = companyRepository;
    }

    public async Task<CompanyDto> CreateAsync(CreateCompanyDto input)
    {
        var entity = ObjectMapper.Map<CreateCompanyDto, Company>(input);
        entity = await _companyRepository.InsertAsync(entity);
        return ObjectMapper.Map<Company, CompanyDto>(entity);
    }

    public async Task<IEnumerable<CompanyDto>> CreateCompaniesAsync(IEnumerable<CreateCompanyDto> input)
    {
        var entities = ObjectMapper.Map<IEnumerable<CreateCompanyDto>, IEnumerable<Company>>(input);
        await _companyRepository.InsertManyAsync(entities);
        return ObjectMapper.Map<IEnumerable<Company>, IEnumerable<CompanyDto>>(entities);
    }

    public async Task DeleteAsync(Guid id)
    {
        await _companyRepository.DeleteAsync(id);
    }

    public async Task<IEnumerable<CompanyDto>> GetAllAsync()
    {
        var entities = await _companyRepository.GetListAsync(includeDetails: true);
        return ObjectMapper.Map<IEnumerable<Company>, IEnumerable<CompanyDto>>(entities);
    }

    public async Task<CompanyDto> GetAsync(Guid id)
    {
        var entity = await _companyRepository.GetAsync(id, includeDetails: true);
        return ObjectMapper.Map<Company, CompanyDto>(entity);
    }

    public async Task<CompanyDto> GetByCodeAsync(string code)
    {
        var entity = await _companyRepository.GetAsync(o => o.Code == code, includeDetails: true);
        return ObjectMapper.Map<Company, CompanyDto>(entity);
    }

    public async Task<CompanyDto> UpdateAsync(Guid id, UpdateCompanyDto input)
    {
        var entity = await _companyRepository.GetAsync(id, includeDetails: true);
        entity = ObjectMapper.Map(input, entity);
        entity = await _companyRepository.UpdateAsync(entity);
        return ObjectMapper.Map<Company, CompanyDto>(entity);
    }

    public async Task<IEnumerable<CompanyDto>> UpdateCompaniesAsync(IDictionary<Guid, UpdateCompanyDto> input)
    {
        var entities = await _companyRepository.GetListAsync(o => input.Keys.Contains(o.Id));
        entities = ObjectMapper.Map(input.Values, entities);
        await _companyRepository.UpdateManyAsync(entities);
        return ObjectMapper.Map<IEnumerable<Company>, IEnumerable<CompanyDto>>(entities);
    }
}

问题现象

执行测试时抛出以下错误:

System.InvalidOperationException : The instance of entity type 'Site' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.

将Site类改为继承AuditedEntity<Guid>后,仅Should_Update_Company测试通过,Should_Create_Company、Should_Create_Companies及Should_Update_Companies测试仍报相同错误。

查阅ABP官方文档及相关Issue后,仍不明确父子实体场景下服务类与DTO类的最佳编写方式,特此咨询。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 04:00:37