代码之家  ›  专栏  ›  技术社区  ›  Darren Wainwright

在异步方法完成之前正在释放EF Core DbContext

  •  3
  • Darren Wainwright  · 技术社区  · 6 年前

    我的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);
            }
        }
    }
    

    我正在通过如下服务调用repo:

    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);
            });
    }); 
    

    错误是:

    enter image description here

    1 回复  |  直到 6 年前
        1
  •  2
  •   mm8    6 年前

    你应该等着 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));
    }