Невозможно получить доступ к удаленному объекту. Причина этой ошибки - Asp. net Исключение ядра, связанное с внедрением зависимости - PullRequest
0 голосов
/ 06 февраля 2020

Я пытаюсь выполнить какую-либо операцию с базой данных при получении сообщения от Azure служебной шины. Я звоню в мою службу, и моя служба внутренне вызывает хранилище для доступа к БД, получения данных и возврата. Но я получаю сообщение об исключении System.ObjectDisposedException при использовании объекта контекста для доступа к моей базе данных

Пожалуйста, проведите меня через это?


startup.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;
    }
}

1 Ответ

0 голосов
/ 06 февраля 2020

Посмотрите на эту строку

services.AddTransient<IServiceBusConsumer, ServiceBusConsumer>();

здесь вы создаете нового потребителя для каждого запроса, по крайней мере, один раз для каждого запроса. Это означает, что вы открываете соединение ServiceBus и закрываете его каждый раз при создании ServiceBusConsumer.

Объекты клиента шины интеграции, такие как QueueClient или MessageSender, создаются через объект MessagingFactory, который также обеспечивает внутреннее управление соединениями. ,

Рекомендуется не закрывать фабрики или очереди сообщений, topi c и клиенты подписки после отправки сообщения, а затем повторно создавать их при отправке следующего сообщения. Закрытие фабрики сообщений удаляет соединение со службой служебной шины, и при воссоздании фабрики устанавливается новое соединение. Установление соединения - дорогостоящая операция, которую вы можете избежать, повторно используя одни и те же объекты фабрики и клиента для нескольких операций. Вы можете безопасно использовать эти клиентские объекты для одновременных асинхронных операций и из нескольких потоков.

См. Рекомендации по улучшению производительности с помощью обмена сообщениями служебной шины

Итак, чтобы исправить эту попытку зарегистрировать его как синглтон

services.AddSingleton<IServiceBusConsumer, ServiceBusConsumer>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...