1

I am getting the following error. Currently following the Async/await pattern And using IServiceScopeFactory. Trying to link the Repo with IQueryable.

Receiving Error below:

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. Object name: 'PropertyContext'.

Repository:

public class AddressRepository
{
    private readonly IServiceScopeFactory _factory;
    public AddressRepository(IServiceScopeFactory factory) : base(factory)
    {
        _factory = factory;

    [EnableQuery]
    public IQueryable<LkAddressType> GetAddressTypes()
    {
        using (var scope = _factory.CreateScope())
        {
            var db = scope.ServiceProvider.GetService<PropertyContext>();
            return db.LkAddressType.AsNoTracking();
        }
    }

App Service:

    public async Task<AddressTypeResponse> GetAddressTypes()
    {
        var data = await (_addressRepository.GetAddressTypes()).ToListAsync();
        var mapped = _mapper.Map<ICollection<AddressTypeModel>>(data);
        var dto = _mapper.Map<ICollection<AddressTypeDto>>(mapped);
        return new AddressTypeResponse {Body = dto};
    }

Controller:

    [HttpGet("AddressType")]
    public async Task<ActionResult<AddressTypeResponse>> GetAddressTypes()
    {
         return Ok(await _service.GetAddressTypes());
    }

Currenly using Net Core 2.2, Entity Framework Core, and OData.

1 Answers1

1

Scope automatically disposes scoped(and transient) objects implementing IDisosable which it created, so when the GetAddressTypes ends, scope and db will be disposed. So you either need to return some wrapper which client will dispose, or materialize query and return result from the method:

[EnableQuery]
public Task<List<LkAddressType>> GetAddressTypes()
{
    using (var scope = _factory.CreateScope())
    {
        var db = scope.ServiceProvider.GetService<PropertyContext>();
        return await db.LkAddressType.AsNoTracking().ToListAsync();
    }
}

Or inject your context directly into the repository and let framework figure out scopes:

public class AddressRepository
{
    private readonly PropertyContext _ctx;
    public AddressRepository(PropertyContext ctx,IServiceScopeFactory factory) : base(factory)
    {
        _ctx= ctx;
     }

    [EnableQuery]
    public IQueryable<LkAddressType> GetAddressTypes()
    {
        return _ctx.LkAddressType.AsNoTracking();
    }
} 
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
  • @marksmith527 why are you creating new scope? why just not inject `PropertyContext` into `AddressRepository` and let framework take are? – Guru Stron Jun 30 '20 at 19:02
  • @marksmith527 also you are materializing query in `AppService.GetAddressTypes` before it becomes available to controller. – Guru Stron Jun 30 '20 at 19:04
  • hi @GuruStron, now it works and selects all the data, however OData does not work, http://localhost:6878/api/Address/AddressType?$top=2 http://localhost:6878/api/Address/AddressType?$select=addressTypeCode –  Jun 30 '20 at 19:16
  • I posted a more elaborate question here, I can send points and close this off, do you happen to know this answer? https://stackoverflow.com/questions/62650392/net-core-using-odata-in-onion-architecture-sending-query-parameters-from-dto-t –  Jun 30 '20 at 19:18
  • @marksmith527 try injecting context into repository as second snippet suggests. I would say that creating scopes manually usually(not always though) is a code smell. – Guru Stron Jun 30 '20 at 19:18
  • I removed OData requirements, placed more elaborate question here https://stackoverflow.com/questions/62650392/net-core-using-odata-in-onion-architecture-sending-query-parameters-from-dto-t –  Jun 30 '20 at 19:20
  • @marksmith527 was glad to help. So on the linked question I could not suggest anything useful. – Guru Stron Jul 01 '20 at 13:11