依赖注入和连接字符串/单例的多个实例
Dependency Injection & connection strings / Multiple instances of a singleton
我有一个严重依赖 Azure Cosmos DB 的 Web Api 项目。到目前为止,拥有一个 Cosmos DB 帐户(一个连接字符串)就足够了。现在一个新的要求是能够根据传入的参数连接到不同的 Cosmos(两个连接字符串)。
对于客户 ID X,我们应该从 Cosmos DB 1 中获取文档,对于另一个客户 Y,我们必须在 Cosmos DB 2 中查找。
到目前为止,我的 Startup.cs 文件注册了 CosmosClient 的单例实例。依次像这样实例化
cosmosClient = new CosmosClient(endpointUrl, primaryKey);
这非常有效。 Web Api 能够轻松处理所有请求。但是现在我们必须为每个请求新建一个 CosmosClient,性能真的很差。
所以我的问题是;有没有办法拥有同一个单例的多个实例?如;我们可以创建组合 Class+EndPointUrl 的单个实例吗? (那还是单例吗?)
现在,我们每分钟都在更新数千个 CosmosClient。与我们之前拥有的相比,我们真的只需要一个。
有多种方法可以做到这一点,但一个简单的实现是围绕您使用的每个 CosmosClient
创建一个包装器。包装器的唯一用途是允许您使用 CosmosClient
的各种实例并按类型区分它们。
//Create your own class for each client inheriting the behaviour of CosmosClient
public class ContosoCosmosClient : CosmosClient
{
public ContosoCosmosClient(string connectionString, CosmosClientOptions clientOptions = null) : base(connectionString, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions = null) : base(accountEndpoint, authKeyOrResourceToken, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions = null) : base(accountEndpoint, tokenCredential, clientOptions)
{
}
}
//In Startup.up add a Singleton for each client
services.AddSingleton(new ContosoCosmosClient(...));
services.AddSingleton(new FabrikamCosmosClient(...));
然后在您的业务逻辑中,您可以添加两个客户端,并根据您的逻辑选择要使用的客户端:
public class MyService
{
public MyService(ContosoCosmosClient contosoClient, FabrikamCosmosClient fabrikamClient)
{
//...
}
}
感谢所有评论和回答。
最后,是不是这种情况,最好的解决方案就是T老师建议的方法https://devblogs.microsoft.com/cosmosdb/httpclientfactory-cosmos-db-net-sdk/
我现在还在使用一个 CosmosClient,Scoped。这允许动态使用端点。
通过注入 IHttpClientFactory 并像这样设置 CosmosClientOptions;
{
HttpClientFactory = () => _httpClientFactory.CreateClient("cosmos")
});
我们现在正在充分利用 HttpClient 及其重用端口的能力。
我有一个严重依赖 Azure Cosmos DB 的 Web Api 项目。到目前为止,拥有一个 Cosmos DB 帐户(一个连接字符串)就足够了。现在一个新的要求是能够根据传入的参数连接到不同的 Cosmos(两个连接字符串)。
对于客户 ID X,我们应该从 Cosmos DB 1 中获取文档,对于另一个客户 Y,我们必须在 Cosmos DB 2 中查找。
到目前为止,我的 Startup.cs 文件注册了 CosmosClient 的单例实例。依次像这样实例化 cosmosClient = new CosmosClient(endpointUrl, primaryKey); 这非常有效。 Web Api 能够轻松处理所有请求。但是现在我们必须为每个请求新建一个 CosmosClient,性能真的很差。
所以我的问题是;有没有办法拥有同一个单例的多个实例?如;我们可以创建组合 Class+EndPointUrl 的单个实例吗? (那还是单例吗?)
现在,我们每分钟都在更新数千个 CosmosClient。与我们之前拥有的相比,我们真的只需要一个。
有多种方法可以做到这一点,但一个简单的实现是围绕您使用的每个 CosmosClient
创建一个包装器。包装器的唯一用途是允许您使用 CosmosClient
的各种实例并按类型区分它们。
//Create your own class for each client inheriting the behaviour of CosmosClient
public class ContosoCosmosClient : CosmosClient
{
public ContosoCosmosClient(string connectionString, CosmosClientOptions clientOptions = null) : base(connectionString, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions = null) : base(accountEndpoint, authKeyOrResourceToken, clientOptions)
{
}
public ContosoCosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions = null) : base(accountEndpoint, tokenCredential, clientOptions)
{
}
}
//In Startup.up add a Singleton for each client
services.AddSingleton(new ContosoCosmosClient(...));
services.AddSingleton(new FabrikamCosmosClient(...));
然后在您的业务逻辑中,您可以添加两个客户端,并根据您的逻辑选择要使用的客户端:
public class MyService
{
public MyService(ContosoCosmosClient contosoClient, FabrikamCosmosClient fabrikamClient)
{
//...
}
}
感谢所有评论和回答。
最后,是不是这种情况,最好的解决方案就是T老师建议的方法https://devblogs.microsoft.com/cosmosdb/httpclientfactory-cosmos-db-net-sdk/
我现在还在使用一个 CosmosClient,Scoped。这允许动态使用端点。
通过注入 IHttpClientFactory 并像这样设置 CosmosClientOptions;
{
HttpClientFactory = () => _httpClientFactory.CreateClient("cosmos")
});
我们现在正在充分利用 HttpClient 及其重用端口的能力。