Azure cosmosdb Cosmos DB:无法访问已处置的对象。对象名称:';释放后访问CosmosClient无效

Azure cosmosdb Cosmos DB:无法访问已处置的对象。对象名称:';释放后访问CosmosClient无效,azure-cosmosdb,Azure Cosmosdb,我得到以下Web Api应用程序服务的例外情况: 类别:Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer事件ID:2请求ID:800001B-0000-6000-b63f-84710c7967bb 请求路径:/api/通知/检索通知SpanId: 93ff3a8b0da39d4f跟踪ID:730bf862b1072a409c402c3b795488ad父ID: 251526087660f84b连接ID“6917529029251694618”,

我得到以下Web Api应用程序服务的例外情况:

类别:Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer事件ID:2请求ID:800001B-0000-6000-b63f-84710c7967bb 请求路径:/api/通知/检索通知SpanId: 93ff3a8b0da39d4f跟踪ID:730bf862b1072a409c402c3b795488ad父ID: 251526087660f84b连接ID“6917529029251694618”,请求ID “8000001b-0000-6000-b63f-84710c7967bb”:发生未处理的异常 由应用程序抛出。例外情况: Microsoft.Azure.Cosmos.CosmosException:响应状态代码不存在 表示成功:InternalServerError(500);子状态:0;活动ID: 00000000-0000-0000-0000-000000000000; 原因:(无法访问 已处置对象。对象名称:'在释放后访问CosmosClient 已处置无效。“);-->System.ObjectDisposedException:无法 访问已处置的对象。对象名称:'访问CosmosClient之后 它已被处置,但无效。“。在 Microsoft.Azure.Cosmos.ClientContextCore.ThrowIfDisposed()位于 Microsoft.Azure.Cosmos.ClientContextCore.ThrowIfDisposed[T](T输入) 在Microsoft.Azure.Cosmos.ClientContextCore.get_DocumentClient()上 Microsoft.Azure.Cosmos.CosmosClient.get_DocumentClient()位于 Microsoft.Azure.Cosmos.Handlers.TransportHandler.ProcessMessageAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.TransportHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.AbstractRetryHandler.ExecuteHttPrequesAsync(Func`2 callbackMethod,Func`4 callShouldRetry,Func`4 callShouldRetryException、ITrace跟踪、CancellationToken 取消令牌)在 Microsoft.Azure.Cosmos.Handlers.AbstractRetryHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(字符串 ResourceUristing,ResourceType,ResourceType,OperationType 操作类型、请求选项、请求选项、容器内部 cosmosContainerCore、FeedRange FeedRange、溪流有效载荷、, 操作'1 requestEnricher、ITrace跟踪、CancellationToken 取消令牌)在 Microsoft.Azure.Cosmos.CosmosQueryClientCore.ExecuteItemQueryAsync(字符串 resourceUri,ResourceType ResourceType,OperationType OperationType, Guid clientQueryCorrelationId,FeedRange FeedRange, QueryRequestOptions请求选项,SqlQuerySpec SqlQuerySpec,字符串 continuationToken,布尔值isContinuationExpected,Int32 pageSize, ITrace trace,CancellationToken CancellationToken)位于 Microsoft.Azure.Cosmos.Pagination.NetworkAttachedDocumentContainer.MonadicQueryAsync(SqlQuerySpec sqlQuerySpec,FeedRangeState`1 FeedRangeState,QueryPaginationOptions queryPaginationOptions、ITrace跟踪、CancellationToken 取消令牌)在 Microsoft.Azure.Cosmos.Pagination.PartitionRangePageAsyncEnumerator`2.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Pagination.BufferedPartitionRangePageAsyncEnumerator`2.PrefetchAsync(ITrace trace,CancellationToken CancellationToken)位于 Microsoft.Azure.Cosmos.Pagination.BufferedPartitionRangePageAsyncEnumerator`2.GetNextPageAsync(ITrace trace,CancellationToken CancellationToken)位于 Microsoft.Azure.Cosmos.Pagination.PartitionRangePageAsyncEnumerator`2.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Pagination.CrossPartitionRangePageAsyncEnumerator`2.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel.ParallelCrossPartitionQueryPileLineStage.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Query.Core.Pipeline.LazyQueryPipelineStage.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Query.Core.Pipeline.NameCacheStalRetryQueryPipeLineStage.MoveNextAsync(ITrace 跟踪)在 Microsoft.Azure.Cosmos.Query.Core.Pipeline.CatchAllQueryPipelineStage.MoveNextAsync(ITrace trace)---内部异常堆栈跟踪的末尾---at Microsoft.Azure.Cosmos.ClientContextCore.ThrowIfDisposed()位于 Microsoft.Azure.Cosmos.ClientContextCore.ThrowIfDisposed[T](T输入) 在Microsoft.Azure.Cosmos.ClientContextCore.get_DocumentClient()上 Microsoft.Azure.Cosmos.CosmosClient.get_DocumentClient()位于 Microsoft.Azure.Cosmos.Handlers.TransportHandler.ProcessMessageAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.TransportHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.AbstractRetryHandler.ExecuteHttPrequesAsync(Func`2 callbackMethod,Func`4 callShouldRetry,Func`4 callShouldRetryException、ITrace跟踪、CancellationToken 取消令牌)在 Microsoft.Azure.Cosmos.Handlers.AbstractRetryHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.RequestHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(RequestMessage 请求,取消令牌(取消令牌)位于 Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler.SendAsync(字符串 ResourceUristing,ResourceType,ResourceType,OperationType 操作类型、请求选项、请求选项、容器内部 cosmosContainerCore、FeedRange FeedRange、Stream STREAMS PAYL
 public class Startup
    {
        private const string CosmosDBEndpoint = "CosmosDBEndpoint";
        private const string CosmosDBAuthKey = "CosmosDBAuthKey";

        public IConfiguration Configuration { get; }

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            RegisterCosmosClient(services, Configuration);
            services.AddTransient(typeof(ICosmosDbRepository<>), typeof(CosmosDbRepository<>));

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "Shell Fleet Hub Notifications WebApi", Version = "v1", });
            });
        }

        // 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();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
                endpoints.MapControllers();
            });

            app.UseSwagger();

           
        }

        private static void RegisterCosmosClient(IServiceCollection serviceCollection, IConfiguration configuration)
        {
            string cosmosDbEndpoint = configuration[CosmosDBEndpoint];
            string cosmosDbAuthKey = configuration[CosmosDBAuthKey];


            serviceCollection.AddSingleton(s => new CosmosClient(cosmosDbEndpoint, cosmosDbAuthKey,
                new CosmosClientOptions { AllowBulkExecution = true }));
        }
    }
public class CosmosDbRepository<T> : ICosmosDbRepository<T> where T : class
    {
        public static readonly string CollectionId = GetAttributeCosmoDbCollection<T>(typeof(T));
        private readonly CosmosClient _client;
        private Container _container;
        private Database _database;
        private const string CosmosDbId = "CosmosDbId";
        private readonly IGetConfigurationSettings _configurationSettings;

        public CosmosDbRepository(CosmosClient client, IGetConfigurationSettings configurationSettings)
        {
            _client = client;
            _configurationSettings = configurationSettings;
            Task.Run(async () =>
            {
                await CreateDatabaseIfNotExistsAsync();
                await CreateContainerIfNotExistsAsync();
            }).Wait();
        }

        public async Task<ItemResponse<T>> CreateItemAsync(T item, string partitionKeyValue)
        {
            return await _container.CreateItemAsync<T>(item, new PartitionKey(partitionKeyValue));
        }

        public async Task<IEnumerable<T>> GetItemsAsync(string queryString)
        {
            var query = _container.GetItemQueryIterator<T>(new QueryDefinition(queryString));

            List<T> results = new List<T>();

            while (query.HasMoreResults)
            {
                var response = await query.ReadNextAsync();

                results.AddRange(response.ToList());
            }
            return results;
        }

        public async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByDesc, int takeCount = -1)
        {
            var criteria = _container.GetItemLinqQueryable<T>(true,
                continuationToken: null,
                new QueryRequestOptions { MaxItemCount = takeCount })
                .Where(predicate)
                .OrderByDescending(orderByDesc)
                .ToFeedIterator();

            var query = criteria;

            var results = new List<T>();
            while (query.HasMoreResults)
            {
                if (takeCount > -1 && results.Count >= takeCount) break;
                results.AddRange(await query.ReadNextAsync());
            }

            return results;
        }

        public async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByDesc, string partitionKey, int takeCount = -1)

        {
            var criteria = _container.GetItemLinqQueryable<T>(allowSynchronousQueryExecution: false,
                continuationToken: null,
                new QueryRequestOptions { PartitionKey = new PartitionKey(partitionKey) })
                .Where(predicate)
                .OrderByDescending(orderByDesc)
                .ToFeedIterator();

            var query = criteria;

            var results = new List<T>();
            while (query.HasMoreResults)
            {
                if (takeCount > -1 && results.Count >= takeCount) break;
                results.AddRange(await query.ReadNextAsync());
            }

            return results;
        }

        public Task<ItemResponse<T>> UpdateItemAsync(string id, T item)
        {
            return _container.ReplaceItemAsync<T>(item, id);
        }

        private async Task CreateDatabaseIfNotExistsAsync()
        {
            _database = await _client
                .CreateDatabaseIfNotExistsAsync(_configurationSettings.Get(CosmosDbId));
        }

        private async Task CreateContainerIfNotExistsAsync()
        {
            _container = await _database
                .CreateContainerIfNotExistsAsync(new ContainerProperties(CollectionId, $"/{GetPartitionKeyAttributeCosmoDbCollection(typeof(T))}"));
        }

        private string GetPartitionKeyAttributeCosmoDbCollection(Type t)
        {
            var attribute = (CosmoDBContainerAttribute)Attribute.GetCustomAttribute(t, typeof(CosmoDBContainerAttribute));
            return attribute.PartitionKey;
        }

        private static string GetAttributeCosmoDbCollection<T>(Type t)
        {
            var attribute = (CosmoDBContainerAttribute)Attribute.GetCustomAttribute(t, typeof(CosmoDBContainerAttribute));
            return attribute.Name;
        }
    }
public class RetrieveUserSubscriptionQueryHandler : IQueryHandler<RetrieveUserSubscriptionQuery, ResultDto>
    {
        private readonly ICosmosDbRepository<UserSubscriptions> _userSubscriptionRepository;

        public RetrieveUserSubscriptionQueryHandler(ICosmosDbRepository<UserSubscriptions> userSubscriptionRepository)
        {
            _userSubscriptionRepository = userSubscriptionRepository;
        }

        public async Task<ResultDto> HandleAsync(RetrieveUserSubscriptionQuery query, ILogger logger)
        {
            logger.LogInformation($"Started {nameof(RetrieveNotificationQueryHandler)} with UUID:{query.UserUUId}");

            var userSubscriptions = await GetUserSubscriptions(query, logger);

            return new ResultDto
            {
                ResultType = ResultType.Success,
                Data = userSubscriptions
            };
        }
        private async Task<UserSubscriptionDto> GetUserSubscriptions(RetrieveUserSubscriptionQuery query, ILogger logger)
        {
            var dto = new UserSubscriptionDto
            {
                UserId = query.UserUUId,
                Subscriptions = new List<SubscriptionDto>(),
                UiNotifications = new List<NotificationCategoryType>(),
                EmailNotifications = new List<NotificationCategoryType>()
            };

            var userSubscriptions = await _userSubscriptionRepository
                                        .GetItemsAsync(s => s.UUID == query.UserUUId, o => o.UUID);

            if (userSubscriptions.Any())
            {
                logger.LogInformation($"subscriptions found for UUID:{query.UserUUId}");

                foreach (var userSubscription in userSubscriptions)
                {
                    if (userSubscription.Type.Equals(UserSubscriptionType.Subscription.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (var item in userSubscription.Events)
                        {
                            var notificationCategory = Utility.GetNotificationCategoryType((NotificationType)item.EventType);

                            if (item.Channels.Any(x => x == (int)ChannelType.UI) && !dto.UiNotifications.Contains(notificationCategory))
                            {
                                dto.UiNotifications.Add(notificationCategory);
                            }
                            if (item.Channels.Any(x => x == (int)ChannelType.Email) && !dto.EmailNotifications.Contains(notificationCategory))
                            {
                                dto.EmailNotifications.Add(notificationCategory);
                            }
                        }
                    }
                    else if (userSubscription.Type.Equals(UserSubscriptionType.Accounts.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (var payer in userSubscription.Payers)
                        {
                            dto.Subscriptions.Add(new SubscriptionDto
                            {
                                PayerNumber = payer.PayerNumber,
                                AccountNumbers = payer.Accounts
                            });
                        }
                    }
                }
            }
            else
            {
                logger.LogInformation($"No subscriptions found for UUID:{query.UserUUId}");
            }
            return dto;
        }
    }