封装CosmosDB连接至函数时出现运行时失败,求原因解析
CosmosClient被释放错误的原因及解决方法
错误原因
你在函数里用using声明了CosmosClient,当函数执行完毕返回Container后,using代码块会自动调用CosmosClient的Dispose方法释放资源。但Container对象内部依赖于创建它的CosmosClient实例,后续你尝试使用这个返回的Container时,它引用的CosmosClient已经被销毁,所以触发了CosmosObjectDisposedException。
而不封装成函数时,CosmosClient的生命周期还没结束(比如在主函数作用域内),所以不会出现这个问题。
解决方法
按照Azure Cosmos DB的官方最佳实践,CosmosClient必须作为单例使用——它本身是线程安全的,且会维护连接池,重复创建实例会导致性能损耗,还容易引发资源释放问题。
修改步骤:
- 把
CosmosClient实例定义为全局静态单例,避免每次调用函数都创建新实例,也不要用using自动释放。 - 在连接函数中使用这个单例
CosmosClient来获取数据库和容器。
修改后的代码示例:
// 全局静态单例CosmosClient,程序启动时初始化一次即可 private static readonly CosmosClient _cosmosClient = new CosmosClient( accountEndpoint: "https://xxxxxxxxxxxxxxx/", authKeyOrResourceToken: "=xxxxxxxxxxxxx=" ); public static async Task<Container> connectToCosmosAsync() { // 使用单例CosmosClient操作数据库 Database database = await _cosmosClient.CreateDatabaseIfNotExistsAsync( id: "uniconta" ); Console.WriteLine($"New database: {database.Id}"); Container container = await database.CreateContainerIfNotExistsAsync( id: "uniconta", partitionKeyPath: "/id", throughput: 400 ); Console.WriteLine($"New container: {container.Id}"); return container; }
这样修改后,CosmosClient的生命周期和程序一致,返回的Container也能正常使用,同时还能提升Cosmos DB操作的性能。
内容的提问来源于stack exchange,提问作者Kresten
相关产品推荐
相关产品推荐

