在异步方法完成之前就将EF Core DbContext处理掉了

时间:2018-08-21 13:39:19

标签: c# entity-framework dbcontext ef-core-2.0

我遇到了DbContext的早期处置问题。仅当调用任何* Async方法(例如ToListAsync())时,如果我调用任何同步方法,一切都很好。

我不知道自己在做什么错。

有什么建议吗?

这里有很多我认为需要的代码。

DbContext及其接口

public interface IMyDbContext
{
    DbSet<MyModel> MyModels { get; set; }
}

public class MyDbContext : DbContext, IMyDbContext
{
    public DbSet<MyModel> MyModels { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

    }

    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new MyModelConfig());           
    }
}

使用此DbContext的存储库

public class MyModelRepository : IMyModelRepository
{
    private readonly IMyDbContext _dbContext;
    private string _baseSql = "Some SQL here ";

    public MyModelRepository(IMyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<IList<MyModel>> GetAllAsync(Paging paging, Permission permission)
    {

        if (permission == null)
            throw new ArgumentNullException("permission");

        string sql = ApplyFilter(_baseSql, permission);

        try
        {
            // THIS FAILS
            return await _dbContext.MyModels.FromSql(sql).Skip(paging.Skip).Take(paging.Take).ToListAsync();

            // THIS FAILS
            return await _dbContext.MyModels.FromSql(sql).ToListAsync();

            // THIS WORKS
            return await _dbContext.MyModels.FromSql(sql).ToList(); 

        }
        catch (Exception e)
        {

            throw new InvalidOperationException("Could not retrieve data", e);
        }
    }
}

我正在通过如下所示的服务调用回购协议:

public class GetAllMyModelQuery : IGetAllMyModelQuery
{
    private readonly IMyModelRepository _myModelRepository;
    private readonly IPermissionService _permissionService;
    private readonly ILogger _logger;

    public GetAllAbsenceQuery(IMyModelRepository myModelRepository, IPermissionService permissionService, ILogger<GetAllMyModelQuery> logger)
    {
        _myModelRepository = myModelRepository;
        _permissionService = permissionService;
        _logger = logger;
    }

    public async Task<IList<Emp_AbsenceEtrac>> Execute(Paging paging)
    {
        if (_permissionService.Permission == null)
        {
            _logger.LogInformation("No permission to the requested resource");
            return null;
        }

        // if external?
        // call external repo

        //TODO//

        // else
        return await _myModelRepository.GetAllAsync(paging, _permissionService.Permission);
    }
}

这又被控制器调用

public class MyModelController : Controller
{
    private readonly IQueryStore _queryStore;

    public MyModelController(IQueryStore queryStore)
    {
        _queryStore = queryStore;
    }

    [HttpGet]
    [ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
    [ProducesResponseType(typeof(BadRequestObjectResult), (int)HttpStatusCode.BadRequest)]
    public async Task<IActionResult> Index([FromQuery] int offset = 0, [FromQuery] int limit = 25)
    {
        Paging paging = new Paging(offset, limit);
        return Ok(_queryStore.GetAllMyModelQuery.Execute(paging));
    }
}

最后,它们在启动时都连接在一起了:

services.AddScoped<IMyDbContext, MyDbContext>();
services.AddScoped<IMyModelRepository, MyModelRepository>();    
// Everything else above is also added as scope..

 services.AddDbContext<MyDbContext>(opts =>
{
    opts.UseSqlServer(Configuration.GetConnectionString("MyDb"),
        sqlServerOptions =>
        {
            sqlServerOptions.CommandTimeout(600);
            // required to allow skip/take on sql server 2008
            sqlServerOptions.UseRowNumberForPaging(true);
        });
}); 

是否有任何跳出会导致我的异步调用导致Db连接关闭的情况?

错误是:

enter image description here

1 个答案:

答案 0 :(得分:2)

您应该在GetAllMyModelQuery.Execute控制器操作中等待Index方法:

[HttpGet]
[ProducesResponseType(typeof(int), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(BadRequestObjectResult), (int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> Index([FromQuery] int offset = 0, [FromQuery] int limit = 25)
{
    Paging paging = new Paging(offset, limit);
    return Ok(await _queryStore.GetAllMyModelQuery.Execute(paging).ConfigureAwait(false));
}