Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当从web套接字订阅访问时,将释放ApplicationDbContext_C#_Asp.net Core - Fatal编程技术网

C# 当从web套接字订阅访问时,将释放ApplicationDbContext

C# 当从web套接字订阅访问时,将释放ApplicationDbContext,c#,asp.net-core,C#,Asp.net Core,我有一个单例服务,它由一个bot集合和从集合中添加/删除bot的方法组成 当web套接字订阅调用\u orderService.getPrelastorerasync(dateTime)时,问题出现在BinanceBot.DoWork(…)中(下面有注释)。原因是ApplicationDbContext已被释放 BinanceBot.DoWork(在web套接字的订阅之外)中的第一个GetPreLastOrderAsync调用工作正常,但另一个(在订阅内部)抛出了一个异常,即处理Applicat

我有一个单例服务,它由一个bot集合和从集合中添加/删除bot的方法组成

当web套接字订阅调用
\u orderService.getPrelastorerasync(dateTime)
时,问题出现在
BinanceBot.DoWork(…)
中(下面有注释)。原因是
ApplicationDbContext
已被释放

BinanceBot.DoWork
(在web套接字的订阅之外)中的第一个GetPreLastOrderAsync调用工作正常,但另一个(在订阅内部)抛出了一个异常,即处理ApplicationDbContext

无法访问已释放的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果您正在调用Dispose

下面的代码已注释,请查看DoWork方法

问题是,既然ApplicationDbContext在那个时候被释放,我如何从web套接字的订阅事件中访问任何与EF核心相关的内容(在本例中是订单)

代表问题的图像:

//Startup.cs
services.AddSingleton();
services.addScope();
services.addScope();
services.addScope();
//OrderService.cs
公共类OrderService:IOrderService
{
私有只读BinanceDbContext_context;
公共OrderService(BinanceDbContext上下文)
{
_上下文=上下文;
}
公共异步任务GetPreLastOrderAsync(日期时间开始时间)
{
var asd=\u context;//已释放
列出订单=等待_context.orders
.其中(e=>e.PlacedAt>startTime)
.包括(e=>e.Bot)
.ToListAsync();
int ordersont=orders.Count;
如果(订单量<2)
{
返回null;
}
returnorders.SingleOrDefault(e=>e.Id==ordersCount-2);
}
}
//其余的
公共接口IBotManagementService
{
任务AddBotAsync(字符串botName);
void RemoveBot(字符串botName);
}
公共类BotManagementService:IBotManagementService
{
私有只读静态ConcurrentDictionary _bots=新ConcurrentDictionary();
公共异步任务AddBotAsync(字符串botName)
{
使用var scope=_serviceProvider.CreateScope();
var botService=scope.ServiceProvider.GetRequiredService();
var notificationService=scope.ServiceProvider.GetRequiredService();
var orderService=scope.ServiceProvider.GetRequiredService();
var bot=await botService.GetByNameAsync(botName);
CancellationTokenSource cts=新的CancellationTokenSource();
Task Task=Task.Factory.StartNew(()=>newbinancebot(notificationService,orderService).DoWork(bot,cts.Token));
_TryAdd(botName,新元组(task,cts));
}
public void RemoveBot(字符串botName)
{
foreach(虚拟机器人中的虚拟机器人)
{
if(bot.Key.Contains(botName))
{
CancellationTokenSource cts=bot.Value.Item2;
cts.Cancel();
_bots.TryRemove(botName,out);
}
}
}
}
公共类BinanceBot:IDisposable
{
私有只读iBanceClient\u客户端;
私有只读iBananceCheckClient\u socketClient;
私有只读INotificationService(通知服务);
专用只读IOrderService _orderService;
public BinanceBot(INotificationService notificationService、IOrderService orderService)
{
_client=newbinanceclient();
_socketClient=新的BinanceSocketClient();
_notificationService=notificationService;
_orderService=orderService;
}
私有更新订阅\ u订阅;
公共无效DoWork(Bot、CancellationToken和token)
{
var prelastOrder=\u orderService.GetPreLastOrderAsync(DateTime.UtcNow.GetAwaiter().GetResult();//此调用工作正常,但下面的调用(在订阅中)引发异常
var subResult=_socketClient.SubscribeToKlineUpdates(bot.CryptoPair.Symbol、bot.TimeInterval.Interval、异步数据=>
{
var helper=newbinancehelper(\u notificationService,\u orderService);
...
var prelastOrder=await _orderService.GetPreLastOrderAsync(redisBot.StartTime);//此处引发异常,但它实际出现在方法中,因为ApplicationDbContext已被释放
});
if(subResult.Success)
{
_订阅=子结果。数据;
}
}
private bool_disposed=false;
公共空间处置()
{
处置(真实);
总干事(本);
}
受保护的虚拟void Dispose(bool disposing)
{
如果(_)
返回;
如果(处置)
{
_client.Dispose();
_socketClient.Dispose();
}
_这是真的;
}
}
公共类BinanceHelper:IDisposable
{
私有只读iBanceClient\u客户端;
私有只读INotificationService(通知服务);
专用只读IOrderService _orderService;
public BinanceHelper(INotificationService notificationService、IOrderService orderService)
{
_client=newbinanceclient();
_notificationService=notificationService;
_orderService=orderService;
}
公共void TestMethod()
{
wait _notificationService.SendNotificationAsync(“Test”);//工作正常
订单=新订单();
...
wait\u orderService.CreateAsync(订单);
}
}
解决方案:

为了解决这个问题,我通过BinanceBot和BinanceHelper的构造函数传递了IServiceProvider。这基本上不是在BotManagementService上创建一个作用域(稍后处理DbContext),而是在每次订阅弹出时创建一个新的作用域

var subResult = _socketClient.SubscribeToKlineUpdates(bot.CryptoPair.Symbol, bot.TimeInterval.Interval, async data =>
{
    using var scope = _serviceProvider.CreateScope();
    var notificationService = scope.ServiceProvider.GetRequiredService<INotificationService>();
    var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();

    ...
}