簡體   English   中英

如何在 OnModelCreating() 中使用 Scoped Service 在每個 HTTP 請求之后 Dispose()?

[英]How to Dispose() after every HTTP request using Scoped Service in OnModelCreating()?

我有一個多租戶應用程序,對於每個HTTP Request ,它應該驗證屬性AccountIdHeaders

全局查詢過濾器是隔離.NET 核心文檔中提到的租戶的好方法,但它沒有列出如何在每次請求后處理 state。

這是一個例子:

ApplicationDbContext.cs有一個使用FooHeaderService注入的AccountIdAccount實體的全局查詢過濾器

private readonly IFooHeader _fooHeaders;

public ApplicationDbContext(IFooHeader fooHeaders) : base(options)
{
    this._fooHeaders = fooHeaders;
}

protected override void OnModelCreating() {
    FooHeaders foo = this._fooHeaders.GetFooHeaders().AccountId;

    // or using Microsoft.EntityFrameworkCore.Infrastructure
    FooHeaders foo = this.Database.GetService<IFooHeaders>();
    Guid fooId = foo.AccountId;     // MUST DISPOSE BETWEEN REQUESTS!

    // Global Query Filter
    modelBuilder.Entity<Account>()
        .HasQueryFilter(filter => filter.AccountId = fooId)
}

FooHeaderService獲取AccountId的標Headers

public class FooHeaderService : IFooHeaders
{
    private readonly FooHeaders _headers;

    public FooHeaderService(IHttpContextAccessor contextAccessor)
    {
        _headers.AccountId = contextAccessor.HttpContext?.Request
             .Headers["accountId"].ToString();
    }

    public FooHeaders GetFooHeaders() => _headers;
}

Startup.csFooHeaderService注冊為ScopedService

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    services.AddScoped<IFooHeader, FooHeaderService>();

    services.AddDbContext<ApplicationDbContext>();
}

問題

如果沒有正確處理, OnModelCreating()中的變量fooId = AccountIdHTTP Requests之間持續存在(非常危險的東西。)。

您如何將 FooHeaderService 依賴注入FooHeaderService OnModelCreating()並為每個HTTP Request周期處理 state?

在此處查看示例: https://github.com/dotnet/EntityFramework.Docs/blob/master/samples/core/Querying/QueryFilters/BloggingContext.cs

OnModelCreating 只運行一次,因此您無法在那里解析特定的 AccountId。 而是將一個服務傳遞給您的 DbContext 構造函數,該構造函數允許您訪問 AccountId。 您實際上已經這樣做了,只是沒有在 OnModelCreating 中使用它。

所以這應該是

public ApplicationDbContext(IFooHeader fooHeaders) : base(options)
{
    this._fooHeaders = fooHeaders;
}

protected override void OnModelCreating() {

    // Global Query Filter
    modelBuilder.Entity<Account>()
        .HasQueryFilter(filter => filter.AccountId = this._fooHeaders.AccountId)
}

這樣,每個 Request 都會獲得一個新的 DbContexts(因為它是作用域的),並且每個 DbContext 都有不同的 IFooHeaders 以插入到全局查詢過濾器中。

您可以使用HttpResponse.RegisterForDisposal方法:

HttpContext.Response.RegisterForDisposal(fooId);

暫無
暫無

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

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