簡體   English   中英

DotNetCore WebAPI依賴注入范圍和處置

[英]DotNetCore WebAPI Dependency Injection Scope and Disposal

我有一個dot net core 2.0 web api。 API使用JWT授權,通常返回json響應。

我將數據庫上下文注入存儲庫,然后將存儲庫注入控制器構造函數,它適用於單個請求。

在Startup.cs中,我已經注冊了存儲庫和上下文,如下所示:

services.AddMvc();
services.AddDbContext<SPContext>(cfg => cfg.UseSqlServer(_config["SPConnectionString"]));
services.AddScoped<ISPRepository, SPRepository>();

存儲庫構造函數:

private SPContext _context { get; }
public SPRepository(SPContext context, ILogger<SPRepository> logger)
    {
        _context = context;
        _logger = logger;
    }

Controller構造函數:

private static ISPRepository _repository;
public ChartsController( ILogger<ChartsController> logger, ISPRepository repository)
{
        _repository = repository;
        _logger = logger;    
}

在我的方法中,我有:

 [HttpGet]
 [Route("api/v1/charts/dashboard/my")]
 public async Task<IActionResult> GetMyDashboards()
    {
        SPUser user = _repository.GetUserByOid(this.User.Identity.Name);
        return Ok(_repository.GetMyDashboards(user));
    }

對於此方法的單個GET請求,我得到一個沒有錯誤的結果,如果我在發送下一個請求之前等待執行完成,它也可以正常工作。

在測試過程中,我碰巧有多個請求同時關閉到此路由。 結果是對第一個的響應,然后是其余的“500”錯誤。

錯誤日志將錯誤顯示為:

System.InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

但是,如果我將存儲庫注入方法,而不是控制器:

[HttpGet]
[Route("api/v1/charts/dashboard/my")]
public async Task<IActionResult> GetMyDashboards([FromServices]ISPRepository _repository)
    {
        SPUser user = _repository.GetUserByOid(this.User.Identity.Name);
        return Ok(_repository.GetMyDashboards(user));
    }

然后請求全部成功,即使同時被解雇。

我的理解是,注冊為作用域的對象僅在單個請求的生命周期內可用,並且當新請求進入系統時將創建新實例。 因此,根據我的理解,第二個請求應該導致創建一組新對象。

注冊服務或控制器的方式有問題嗎? 或者這是依賴注入的預期行為?

您應該刪除控制器中_repository的'static'屬性。 因為這意味着控制器的所有實例將共享同一個存儲庫。

當第一個請求仍在處理時觸發第二個請求時,您將使用存儲庫的新實例創建控制器的新實例。 這很好,但是因為_repository是靜態的,所以它也將與控制器的第一個實例共享,替換之前創建的實例。

然后兩個控制器將調用相同的底層DbContext,從而導致您的問題。

當您手動注入存儲庫時,所有內容都是分開的,這就是為什么它適合您。

一個好的做法是使您的屬性只讀,以確保它們只在構造函數中初始化一次,並且以后不能覆蓋。

private readonly ISPRepository _repository;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM