Search code examples
c#automapperdtounit-of-workasp.net-boilerplate

AppService returns DTO with null Id


I am implementing AppService and DomainService.

DomainService:

public class TagsManager : IDomainService
{
    private readonly IRepository<Tag, long> _tagRepository;
    private readonly IUnitOfWorkManager _unitOfWorkManager;

    public TagsManager(IRepository<Tag, long> tagRepository, IUnitOfWorkManager unitOfWorkManager)
    {
        _tagRepository = tagRepository;
        _unitOfWorkManager = unitOfWorkManager;
    }

    public IQueryable<Tag> Tags
    {
        get { return _tagRepository.GetAll(); }
    }
}

When using DomainService in AppService:

[UnitOfWork(IsDisabled = true)]
public async Task<TagDto> CreateTag(CreateTagInput input)
{
    var existing = await _tagsManager.Tags.Where(p => p.Type == input.Type && p.Value == input.Value.Trim()).FirstOrDefaultAsync();
    if (existing != null) throw new UserFriendlyException(L("ExistedRepeatedTag"));
    var newEntity = ObjectMapper.Map<Tag>(input);
    await _tagsManager.CreateTag(newEntity);
    return ObjectMapper.Map<TagDto>(newEntity);
}

It will throw exception:

Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.

If I comment out [UnitOfWork(IsDisabled = true)], I will need _unitOfWorkManager to save the record. Otherwise, in my Test project, code below returns tag with null Id.

var tag = await _tagAppService.CreateTag(new CreateTagInput
{
    Value = createTag
});

Solution

  • Don't disable UnitOfWork. You need to call SaveChanges before mapping.

    // [UnitOfWork(IsDisabled = true)]
    public async Task<TagDto> CreateTag(CreateTagInput input)
    {
        var existing = await _tagsManager.Tags.Where(p => p.Type == input.Type && p.Value == input.Value.Trim()).FirstOrDefaultAsync();
        if (existing != null) throw new UserFriendlyException(L("ExistedRepeatedTag"));
        var newEntity = ObjectMapper.Map<Tag>(input);
        await _tagsManager.CreateTag(newEntity);
    
        // await _unitOfWorkManager.Current.SaveChangesAsync();
        await CurrentUnitOfWork.SaveChangesAsync();
    
        return ObjectMapper.Map<TagDto>(newEntity);
    }