我有一個資料串列,它并不大(大約 400 項)。它存盤在 MySQL 資料庫中,我想將它快取到 ASP.NET Core 以防止頻繁讀取它。更重要的是,資料將每小時重繪 一次。
這是我的代碼:
public class IPCheckService
{
readonly SIComponent.Database.BLContext Context;
public IPCheckService(SIComponent.Database.BLContext Context)
{
this.Context = Context;
}
List<SIComponent.Database.IPAndUAModel> _IPBlackList = null;
public List<SIComponent.Database.IPAndUAModel> IPBlackList
{
get
{
if (DateTime.Now - LastUpdateTime > TimeSpan.FromHours(2))
{
if (Context.IpBlackList.Count() != _IPRangeBlackList.Count)
{
_IPRangeBlackList = new List<SIComponent.Database.IPAndUAModel>(Context.IpBlackList);
}
LastUpdateTime = DateTime.Now;
}
if (_IPBlackList == null)
{
_IPBlackList = new List<SIComponent.Database.IPAndUAModel>(Context.IPBlackList);
}
return _IPBlackList;
}
}
DateTime LastUpdateTime = DateTime.Now;
}
更重要的是,上面的代碼是服務的一部分,它是一個單例服務。
程式運行后,我做的例外中間件有時會捕捉到這個例外:
在創建模型時嘗試使用該模型。不能以任何方式在“OnModelCreating”中使用 DbContext 實體,以利用正在創建的模型。
在 Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel(Boolean designTime)
在 Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
在 Microsoft.EntityFrameworkCore.DbContext.get_Model()
在 Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityType() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.CheckState()
在Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.get_EntityQueryable() at Microsoft.EntityFrameworkCore.Internal.InternalDbSet1.System.Collections.Generic.IEnumerable.GetEnumerator()
在 System.Collections.Generic.List1..ctor(IEnumerable1 集合)
在 abc.Services.IPCheckService.get_IPBlackList() 在 C:\Project\abc\Services \IPCheckService.cs:line 12
at abc.Middlewares.IPAccessCheck(IPModel IP) in C:\Project\abc\Middlewares\IPAccessCheckMiddleware.cs:line 701
at lambda_method9(Closure , Object)
在 Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
在 Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.g__Awaited|12_0(ControllerActionTaskInvoker1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|8_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Taskmatch ) 在 C:\Project\abc\Middlewares\ExceptionMiddleware.cs:line 26 中的 abc.Middlewares.ExceptionMiddleware.Invoke(HttpContext context)
我閱讀了一些有關此例外的文章,發現似乎是因為DbContext不能保證和相關類的實體成員是執行緒安全的。
但是,我沒有找到有關如何解決此問題的文章。我該如何解決?謝謝你。
uj5u.com熱心網友回復:
您不能以這種方式使用 DbContext。它通常注冊為作用域服務,但您正試圖將其注入單調。多執行緒也存在問題,您必須保護檢索資料。
好吧,這是我的變體:
public class IPCheckService
{
private readonly IServiceProvider _serviceProvider;
private DateTime _lastUpdateTime;
private List<SIComponent.Database.IPAndUAModel> _IPBlackList = null;
public IPCheckService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public IReadOnlyList<SIComponent.Database.IPAndUAModel> IPBlackList
{
get
{
// you need lock because several threads may access this property concurrently.
lock(this)
{
if (_IPBlackList != null && (DateTime.Now - _lastUpdateTime).TotalHours < 1)
{
return _IPBlackList;
}
// context will be create within scope and automatically disposed
using (var scope = serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetService<SIComponent.Database.BLContext>();
_IPBlackList = context.IPBlackList.ToList();
_lastUpdateTime = DateTime.Now;
}
return _IPBlackList
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/394410.html
