c# - 无法访问已处置的对象。导致此错误 - 与依赖注入相关的 Asp.net 核心异常
问题描述
我正在尝试在从 Azure 服务总线接收消息时执行一些数据库操作。
我正在调用我的服务,并且我的服务在内部调用了一个存储库来访问数据库获取数据并返回,但是我收到一条System.ObjectDisposedException Exception
关于使用上下文对象访问我的数据库的消息。
请指导我完成这个?
启动.cs
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration
{
get;
}
public static string clientId
{
get;
private set;
}
public static string clientSecret
{
get;
private set;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string azureConnectionString = Configuration["ConnectionStrings:DefaultConnection"];
services.AddControllers();
clientId = Configuration.GetSection("fuelSDK").GetSection("clientId").Value;
clientSecret = Configuration.GetSection("fuelSDK").GetSection("clientSecret").Value;
var dbUtils = new AzureDatabaseUtils();
var sqlConnection = dbUtils.GetSqlConnection(azureConnectionString);
services.AddDbContext < DeciemStoreContext > (options = >options.UseSqlServer(sqlConnection));
#region RegisterServices
services.AddTransient < IServiceBusConsumer,
ServiceBusConsumer > ();
services.AddTransient < IOrderRepository,
OrderRepository > ();
services.AddTransient < IOrderService,
OrderService > ();
#endregion
Configuration.GetSection("Global").Get < Global > ();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
#region Azure ServiceBus
using(var scope = app.ApplicationServices.CreateScope())
{
var bus = scope.ServiceProvider.GetService < IServiceBusConsumer > ();
bus.RegisterOnMessageHandlerAndReceiveMessages();
}
#endregion
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints = > {
endpoints.MapControllerRoute("api", "api/{controller}/{action}/{id?}");
});
}
MessageConsumerClass.cs
public interface IServiceBusConsumer
{
void RegisterOnMessageHandlerAndReceiveMessages();
Task CloseQueueAsync();
}
public class ServiceBusConsumer: IServiceBusConsumer
{
private IOrderService _orderService;
private readonly ILogger _logger;
static ISubscriptionClient subscriptionClient;
public ServiceBusConsumer(ILogger < ServiceBusConsumer > logger, IOrderService orderService)
{
_logger = logger;
_orderService = orderService;
const string ServiceBusConnectionString = "Endpoint=sb://qa10em.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=v2sIQi/2fY2rENS7trnFd38m2wqNJKuWYMFJxWccK8E=";
const string TopicName = "businessoperation";
const string SubscriptionName = "SFOperation_sub";
//SubscriberCreateAsync().Wait();
subscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, SubscriptionName);
}
public void RegisterOnMessageHandlerAndReceiveMessages()
{
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler) {
MaxConcurrentCalls = 1,
AutoComplete = false
};
subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
}
private async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
try
{
Console.WriteLine($ "Received message: SequenceNumber:{message.SystemProperties.SequenceNumber} Body:{Encoding.UTF8.GetString(message.Body)}");
var mb = JsonConvert.DeserializeObject < MessageBody > (Encoding.UTF8.GetString(message.Body));
if (mb != null)
{
Global.Entity = mb.Entity;
Global.ActionName = mb.ActionName;
Global.Value = mb.Value;
}
else
{
Global.Entity = "";
Global.ActionName = "";
Global.Value = "";
}
await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
//Here I am calling the service to get data
var orders = _orderService.GetByOrderId(Global.Value);
//await _orderService.GetByOrderId(Global.Value);
}
catch(Exception ex)
{
throw ex;
}
}
OrderRepository.cs——在这个文件中,我收到了 DBContext 处理的异常
protected DeciemStoreContext _context;
public OrderRepository(DeciemStoreContext context)
{
_context = context;
}
public async Task <IEnumerable<Order>> ListAsync()
{
return await _context.Order.ToListAsync();
}
public async Task <List<Order>> GetByOrderId(string OrderId)
{
try
{
int oid = Convert.ToInt32(OrderId);
// here while trying to access _context the context seems to have disposed before
var order = from o in _context.Order
where o.OrderId == oid
orderby o.OrderId
select new Order
{
OrderId = o.OrderId,
CustomerId = o.CustomerId,
ProductSubtotal = o.ProductSubtotal,
PreTaxSubtotal = o.PreTaxSubtotal,
DiscountCode = o.DiscountCode,
DiscountPercent = o.DiscountPercent,
DiscountAmount = o.DiscountAmount,
GrandTotal = o.GrandTotal,
Ponumber = o.Ponumber,
PostedDate = o.PostedDate
};
return await order.ToListAsync();
}
catch(Exception ex)
{
throw ex;
}
}
解决方案
看这条线
services.AddTransient<IServiceBusConsumer, ServiceBusConsumer>();
在这里,您每次被请求时都会创建一个新的消费者(每个请求至少一次)。这意味着您在每次ServiceBusConsumer
创建时打开 ServiceBus 连接并关闭它。
服务总线客户端对象(例如 QueueClient 或 MessageSender)是通过 MessagingFactory 对象创建的,该对象还提供连接的内部管理。
建议您发送消息后不要关闭消息工厂或队列、主题和订阅客户端,然后在发送下一条消息时重新创建它们。关闭消息传递工厂会删除与服务总线服务的连接,并在重新创建工厂时建立新的连接。建立连接是一项昂贵的操作,您可以通过为多个操作重用相同的工厂和客户端对象来避免这种操作。您可以安全地将这些客户端对象用于并发异步操作和来自多个线程。
因此,要解决此问题,请尝试将其注册为单例
services.AddSingleton<IServiceBusConsumer, ServiceBusConsumer>();
推荐阅读
- android - 具有特定活动的多次访问的共享数据
- javascript - 如何在输入字段中使用 bootstrap 4 制作芯片
- r - 在 dplyr group_by 函数中忽略(但不删除)NA
- android - Android - sharedpreferences 数据正在与 apk 一起上传到 Play 商店
- javascript - Firebase 事务未更新/返回 Null
- autodesk-viewer - 如何在 Autodesk-viewer 中设置元素的透明性?
- android - 如何创建 android LatLng 的边界(两点)以显示在屏幕顶部?在安卓中
- python - 如何解析包含不确定数据模式的日志文件?
- javascript - 使用 css、javascript、两个按钮 onclick() 的两个动画
- text - BCP 意外字符串数据,右截断