通过 Azure 函数注入 DbContext 时无法访问已处置的对象

Posted

技术标签:

【中文标题】通过 Azure 函数注入 DbContext 时无法访问已处置的对象【英文标题】:Cannot access a disposed object when injecting DbContext through Azure Function 【发布时间】:2019-11-20 01:22:08 【问题描述】:

我在尝试将 DbContext 注入 Azure 函数时收到以下错误:

Microsoft.EntityFrameworkCore: Cannot access a disposed object.

这是当前函数

    private readonly FundCentreContext _fundCentreContext;

    public GetDailyPrices(FundCentreContext fundCentreContext)
    
        _fundCentreContext = fundCentreContext;
    
    [Produces("application/json")]
    [FunctionName(nameof(GetDailyPrices))]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "api/dailyprices")] HttpRequest req,
        ILogger log)
    

        //Parameters
        var parameters = req.GetQueryParameterDictionary();

        var page = int.Parse(parameters.GetValueOrDefault("page", "0"));
        var limit = int.Parse(parameters.GetValueOrDefault("limit", "10"));
        var offset = int.Parse(parameters.GetValueOrDefault("offset", "0"));
        var sort = parameters.GetValueOrDefault("sort", "asc");

        var fundService = new FundService(_fundCentreContext);

        var fundDailyPrices = fundService.GetAllDailyPricesByPage(page, limit, offset);

        return fundDailyPrices != null
            ? (ActionResult)new OkObjectResult(fundDailyPrices)
            : new BadRequestObjectResult("There was an error with your request");
    

并且使用该服务的启动有以下代码:

services
    .AddDbContext<FundCentreContext>(options =>
        options.UseSqlServer("*ommited*"));

我不知道为什么会发生这个错误 - 调试过去的 return 语句有效,并且可以在 fundDailyPrices 对象中看到数据,但是 return 语句之后的某些东西意外地结束了整个函数。

【问题讨论】:

你的GetAllDailyPricesByPage函数是async吗? 如果没有任何等待,为什么要使用async Task 我打算将 await 添加到 GetAllDailyPricesByPage() 函数,但目前它无论如何都不是异步的。我编辑了问题并删除了异步以消除混乱。使用同步函数仍然会发生错误。 这可能会有所帮助 - ***.com/questions/65242457/… 【参考方案1】:

很难用您提供的代码来判断,但最可能的罪魁祸首是在上下文超出范围之前您没有具体化结果集。同样,我们看不到所有代码,但是当您执行诸如直接返回 IQueryable 之类的操作时会发生这种情况。任何类型的服务调用都应该返回一个具体化列表(即在返回之前对结果集调用ToList()ToListAsync())。如果您启用了该功能,它也可能是由延迟加载引起的。如果是这样,你应该确保所有必要的关系都被急切地加载。

使用注入上下文来更新服务也很奇怪。你应该简单地注入你的服务,因为它对你的上下文有一个构造函数依赖,它将被自动注入它。这可确保两个对象在相同的或至少兼容的生命周期内运行。

另外,不要将IDisposable 与注入的依赖项一起使用。我们无法提供有关您的服务类的任何信息,但如果它确实实现了IDisposable,请将其删除。

【讨论】:

用 EF 注入 DbContext 不是很标准吗?我不确定你为什么不注射一次性的东西。 你把不同的东西混为一谈。这里的问题不是注入服务,而不是上下文。当然应该注入上下文,但是当使用 DI 时,应该注入链上和下的所有内容。第二个问题是在服务类上实现 IDisposable,假设它不拥有任何依赖项。上下文被注入,所以服务类绝对不应该释放上下文,因为它不拥有它。

以上是关于通过 Azure 函数注入 DbContext 时无法访问已处置的对象的主要内容,如果未能解决你的问题,请参考以下文章

注入 dbContext 时返回“找不到与给定参数匹配的构造函数”

使用 DBContext 将 SQL Server 数据库与时间触发的 Azure 函数连接起来

使用 Azure Function 2.x 通过构造函数为 Http 触发函数注入 ILogger

访问 DBContext 而不一直注入它

如何使用 caliburn micro 在 Wpf 中注入 EF DbContext

通过依赖注入实现后台任务的 DbContext