You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#的MongoDBContext中根据UserID动态设置连接字符串

动态根据UserID切换MongoDB连接的实现方案

1. 调整配置文件结构

首先在appsettings.json中按用户ID配置对应的MongoDB连接信息:

"MongoSettings": {
  "Clients": {
    "User123": {
      "ConnectionString": "mongodb://user1-cluster:27017",
      "DatabaseName": "user1_db"
    },
    "User456": {
      "ConnectionString": "mongodb://user2-cluster:27017",
      "DatabaseName": "user2_db"
    }
  }
}

2. 定义配置绑定实体

创建类来映射用户专属的Mongo配置:

public class UserMongoConfig
{
    public string ConnectionString { get; set; }
    public string DatabaseName { get; set; }
}

3. 重构MongoContext

修改上下文类,注入IHttpContextAccessor获取当前用户ID,同时缓存MongoClient避免重复创建:

public class MongoContext
{
    private readonly IConfiguration _configuration;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly Dictionary<string, IMongoClient> _clientCache = new();
    private IMongoDatabase _currentDatabase;
    private string _currentUserId;
    private List<Func<Task>> _commands;

    public MongoContext(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
    {
        _configuration = configuration;
        _httpContextAccessor = httpContextAccessor;
        _commands = new List<Func<Task>>();
    }

    private void ConfigureMongo()
    {
        // 获取当前请求的UserID(需根据实际认证方式调整Claim类型)
        var userId = _httpContextAccessor.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier);
        if (string.IsNullOrEmpty(userId))
        {
            throw new InvalidOperationException("无法获取当前用户标识");
        }

        // 同一用户复用已有数据库连接
        if (_currentUserId == userId && _currentDatabase != null)
        {
            return;
        }

        // 读取当前用户的Mongo配置
        var userConfig = _configuration.GetSection($"MongoSettings:Clients:{userId}").Get<UserMongoConfig>();
        if (userConfig == null)
        {
            throw new KeyNotFoundException($"未找到用户[{userId}]对应的MongoDB配置");
        }

        // 缓存MongoClient(MongoClient是线程安全的,无需每次创建)
        if (!_clientCache.TryGetValue(userId, out var mongoClient))
        {
            mongoClient = new MongoClient(userConfig.ConnectionString);
            _clientCache[userId] = mongoClient;
        }

        _currentDatabase = mongoClient.GetDatabase(userConfig.DatabaseName);
        _currentUserId = userId;
    }

    public IMongoCollection<T> GetCollection<T>(string name)
    {
        ConfigureMongo();
        return _currentDatabase.GetCollection<T>(name);
    }
}

4. 注册服务

在Program.cs中注册所需服务,确保MongoContext为Scoped生命周期(每个请求一个实例):

// 注册HttpContext访问器
builder.Services.AddHttpContextAccessor();
// 注册MongoContext为Scoped
builder.Services.AddScoped<MongoContext>();

关键注意事项

  • MongoClient缓存:MongoClient是线程安全的,缓存它能避免重复创建连接池的开销,提升性能。
  • 生命周期:MongoContext必须注册为Scoped,确保每个请求的上下文独立处理当前用户的连接。
  • 认证适配:获取UserID的方式需根据项目实际认证方案调整(比如JWT中的ClaimKey可能不同)。
  • 异常处理:需针对用户无配置、无法获取UserID等场景添加异常捕获或降级逻辑。

内容的提问来源于stack exchange,提问作者Deepak Gariya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 20:46:33