[英]How to release and dispose all Http-scoped objects on Container instance?
[英]How to Dispose() after every HTTP request using Scoped Service in OnModelCreating()?
我有一個多租戶應用程序,對於每個HTTP Request
,它應該驗證屬性AccountId
的Headers
。
全局查詢過濾器是隔離.NET 核心文檔中提到的租戶的好方法,但它沒有列出如何在每次請求后處理 state。
這是一個例子:
ApplicationDbContext.cs有一個使用FooHeaderService
注入的AccountId
的Account
實體的全局查詢過濾器
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.cs將FooHeaderService
注冊為ScopedService
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IFooHeader, FooHeaderService>();
services.AddDbContext<ApplicationDbContext>();
}
問題
如果沒有正確處理, OnModelCreating()
中的變量fooId = AccountId
在HTTP Requests
之間持續存在(非常危險的東西。)。
您如何將 FooHeaderService 依賴注入FooHeaderService
OnModelCreating()
並為每個HTTP Request
周期處理 state?
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.