Azure cosmosdb Cosmos DB:无法访问已处置的对象。对象名称:';释放后访问CosmosClient无效
我得到以下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 PAYLAzure 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”,
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;
}
}