From 04fa1793b41016b56ff9f1fefba10c286171962d Mon Sep 17 00:00:00 2001 From: sunkaixuan <610262374@qq.com> Date: Sat, 26 Apr 2025 19:34:30 +0800 Subject: [PATCH] Add Mongo DB --- .../MongoDb.Ado.data/MongoDbConnection.cs | 117 +++++++++++++----- Src/Asp.NetCore2/MongoDbTest/AdoTest.cs | 35 ++++-- Src/Asp.NetCore2/MongoDbTest/DbHelper.cs | 15 +++ 3 files changed, 126 insertions(+), 41 deletions(-) create mode 100644 Src/Asp.NetCore2/MongoDbTest/DbHelper.cs diff --git a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs index 9955caa7a..f69568ab7 100644 --- a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs +++ b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs @@ -10,26 +10,23 @@ namespace MongoDb.Ado.data { public class MongoDbConnection : DbConnection { + private static readonly Dictionary _clientCache = new Dictionary(StringComparer.OrdinalIgnoreCase); + private static readonly object _lock = new object(); + private readonly string _originalConnectionString; - private MongoClient _client; private IMongoDatabase _database; - private ConnectionState _state = ConnectionState.Closed; private string _databaseName; - - public override string ConnectionString - { - get => _originalConnectionString; - set => throw new NotSupportedException("Setting ConnectionString after construction is not supported."); - } - + private ConnectionState _state = ConnectionState.Closed; + public override string Database => _databaseName; - public override string DataSource => _client?.Settings?.Server?.ToString() ?? ""; - public override string ServerVersion => "MongoDB_" + (_client?.Cluster?.Description?.ClusterId.ToString() ?? "Unknown"); - public override ConnectionState State => _state; + public override string ConnectionString { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + private MongoClient _client; + public MongoDbConnection(string connectionString) { _originalConnectionString = connectionString; @@ -38,29 +35,84 @@ namespace MongoDb.Ado.data private void ParseAndConnect(string connStr) { + string mongoConnStr; if (connStr.TrimStart().StartsWith("mongodb://", StringComparison.OrdinalIgnoreCase)) { - var mongoUrl = new MongoUrl(connStr); - _client = new MongoClient(mongoUrl); - _databaseName = mongoUrl.DatabaseName ?? "test"; - _database = _client.GetDatabase(_databaseName); - return; + mongoConnStr = connStr; } + else + { + string queryParams = string.Empty; // 用来存储查询参数部分 - var dict = ParsePgStyleConnectionString(connStr); - var host = dict.GetValueOrDefault("Host", "localhost"); - var port = dict.GetValueOrDefault("Port", "27017"); - _databaseName = dict.GetValueOrDefault("Database", "test"); - var username = dict.GetValueOrDefault("Username", ""); - var password = dict.GetValueOrDefault("Password", ""); + // 如果连接字符串以 "mongodb://" 开头 + if (connStr.TrimStart().StartsWith("mongodb://", StringComparison.OrdinalIgnoreCase)) + { + mongoConnStr = connStr; - var mongoConnStr = string.IsNullOrEmpty(username) - ? $"mongodb://{host}:{port}" - : $"mongodb://{Uri.EscapeDataString(username)}:{Uri.EscapeDataString(password)}@{host}:{port}/{_databaseName}"; + // 提取查询参数 + var uri = new Uri(mongoConnStr); + var query = uri.Query; + if (!string.IsNullOrEmpty(query)) + { + queryParams = query; + } + } + else + { + // 解析以 PostgreSQL 风格的连接字符串 + var dict = ParsePgStyleConnectionString(connStr); + var host = dict.GetValueOrDefault("Host", "localhost"); + var port = dict.GetValueOrDefault("Port", "27017"); + _databaseName = dict.GetValueOrDefault("Database", ""); + var username = dict.GetValueOrDefault("Username", ""); + var password = dict.GetValueOrDefault("Password", ""); - var mongoUrlParsed = new MongoUrl(mongoConnStr); - _client = new MongoClient(mongoUrlParsed); - _database = _client.GetDatabase(_databaseName); + mongoConnStr = string.IsNullOrEmpty(username) + ? $"mongodb://{host}:{port}/{_databaseName}" + : $"mongodb://{Uri.EscapeDataString(username)}:{Uri.EscapeDataString(password)}@{host}:{port}/{_databaseName}"; + + // 提取查询参数(如果有) + if (dict.ContainsKey("ReplicaSet")) + { + queryParams += $"?replicaSet={dict["ReplicaSet"]}"; + } + + if (dict.ContainsKey("AuthSource")) + { + if (!string.IsNullOrEmpty(queryParams)) + { + queryParams += "&"; + } + queryParams += $"authSource={dict["AuthSource"]}"; + } + } + mongoConnStr = mongoConnStr + queryParams; + _client = GetOrCreateClient(mongoConnStr); + + if (_databaseName == null) + { + var mongoUrl = new MongoUrl(mongoConnStr); + _databaseName = mongoUrl.DatabaseName ?? "test"; + } + + _database = _client.GetDatabase(_databaseName); + } + } + + private static MongoClient GetOrCreateClient(string connectionString) + { + if (_clientCache.TryGetValue(connectionString, out var client)) + return client; + + lock (_lock) + { + if (_clientCache.TryGetValue(connectionString, out client)) + return client; + + client = new MongoClient(connectionString); + _clientCache[connectionString] = client; + return client; + } } private Dictionary ParsePgStyleConnectionString(string connStr) @@ -72,13 +124,14 @@ namespace MongoDb.Ado.data public override void Open() { - // MongoClient 实际上在操作集合时才连接,我们只改变状态 _state = ConnectionState.Open; } public override void Close() { _state = ConnectionState.Closed; + // 注意:MongoClient 不需要 Dispose,它内部自己管理连接池! + // 所以这里不用处理 _client.Dispose(),否则会出大问题 } protected override DbCommand CreateDbCommand() @@ -97,13 +150,13 @@ namespace MongoDb.Ado.data protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel) { - throw new NotSupportedException("MongoDB does not support transactions via DbTransaction."); + return null; } public IMongoDatabase GetDatabase() => _database; - public MongoClient GetClient() => _client; public override string ToString() => _originalConnectionString; } + } diff --git a/Src/Asp.NetCore2/MongoDbTest/AdoTest.cs b/Src/Asp.NetCore2/MongoDbTest/AdoTest.cs index 510025ab1..9974534c3 100644 --- a/Src/Asp.NetCore2/MongoDbTest/AdoTest.cs +++ b/Src/Asp.NetCore2/MongoDbTest/AdoTest.cs @@ -11,18 +11,35 @@ namespace MongoDbTest { public class AdoTest { - public static void Init() + public static void Init() + { + MongoClientTest(); + MongoDbConnectionTest(); + } + + private static void MongoDbConnectionTest() + { + var db= new MongoDbConnection(DbHelper.SqlSugarConnectionString); + + var database= db.GetDatabase(); + var collections = database.GetCollection("b"); + // 插入一个文档,MongoDB 会创建数据库和集合 + var document = new BsonDocument { { "name", "bbbbbb" }, { "age", 30 } }; + collections.InsertOne(document); + var list = collections.AsQueryable().ToList(); + } + + private static void MongoClientTest() { //开发中 - var client = new MongoClient(""); - var database = client.GetDatabase("test"); + var client = new MongoClient(DbHelper.ConnectionString); + var database = client.GetDatabase("SqlSugarDb"); // 获取当前数据库中的所有集合 - var collections = database.ListCollections(); - - - MongoDbConnection connection = new MongoDbConnection(""); - connection.Open(); - connection.Close(); + var collections = database.GetCollection("a"); + // 插入一个文档,MongoDB 会创建数据库和集合 + var document = new BsonDocument { { "name", "aaaa" }, { "age", 30 } }; + collections.InsertOne(document); + var list = collections.AsQueryable().ToList(); } } } diff --git a/Src/Asp.NetCore2/MongoDbTest/DbHelper.cs b/Src/Asp.NetCore2/MongoDbTest/DbHelper.cs new file mode 100644 index 000000000..1bd92f8b2 --- /dev/null +++ b/Src/Asp.NetCore2/MongoDbTest/DbHelper.cs @@ -0,0 +1,15 @@ +using MongoDB.Driver.Core.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MongoDbTest +{ + public class DbHelper + { + public static string ConnectionString= "mongodb://mongouser:Huangxin%40123@localhost:27018/SqlSugarDb?replicaSet=cmgo-7d07e4w1_0&authSource=admin"; + public static string SqlSugarConnectionString = "host=localhost;Port=27018;Database=SqlSugarDb;Username=mongouser;Password=Huangxin@123;replicaSet=cmgo-7d07e4w1_0&authSource=admin"; + } +}