如何检查与mongodb的连接
我使用MongoDB
驱动程序连接到数据库。 当我的表单加载时,我想设置连接并检查它是否正常。 我是这样做的:
var connectionString = "mongodb://localhost"; var client = new MongoClient(connectionString); var server = client.GetServer(); var database = server.GetDatabase("reestr");
但我不知道如何检查连接。 我尝试将此代码与try-catch
重叠,但无济于事。 即使我创建了一个不正确的connectionString,我仍然无法获得任何错误消息。
有一个ping方法 :
var connectionString = "mongodb://localhost"; var client = new MongoClient(connectionString); var server = client.GetServer(); server.Ping();
要使用新的3.0驱动程序ping服务器:
var database = client.GetDatabase("YourDbHere"); database.RunCommandAsync((Command)"{ping:1}") .Wait();
2.4.3的完整示例 – 其中“client.GetServer()”不可用。 基于“保罗凯斯特”的回答。
client = new MongoClient("mongodb://localhost"); database = client.GetDatabase(mongoDbStr); bool isMongoLive = database.RunCommandAsync((Command)"{ping:1}").Wait(1000); if(isMongoLive) { // connected } else { // couldn't connect }
我和OP有同样的问题,尝试了我能在互联网上找到的每一个解决方案……好吧,没有一个能让我真正满意,所以我选择了一项研究来找到一个可靠的以及检测是否存在与MongoDB数据库服务器的连接的响应方式。 这不会阻止应用程序的同步执行太长时间……
所以这是我的先决条件:
- 连接检查的同步处理
- 连接检查的时间片很短到很短
- 连接检查的可靠性
- 如果可能,不抛出exception而不触发超时
我在默认的localhost URL上提供了一个全新的MongoDB安装(版本3.6): mongodb:// localhost:27017 。 我还写下了另一个URL,其中没有MongoDB数据库服务器: mongodb:// localhost:27071 。
我也使用C#Driver 2.4.4并且不使用遗留实现(MongoDB.Driver.Legacy程序集)。
所以我的期望是,当我检查与第一个URL的连接时,它应该给我一个与现有MongoDB服务器的活动连接的确定,当我检查它应该给我的第二个URL的连接时对于不存在的MongoDB服务器失败…
使用IMongoDatabase.RunCommand方法查询服务器并导致服务器响应超时,因此不符合先决条件。 此外,在超时后,它会因TimeoutException而中断,这需要额外的exception处理。
这个实际的SO问题以及这个问题已经提供了我解决方案所需的大部分启动信息……所以大家好,非常感谢!
我的解决方案:
private static bool ProbeForMongoDbConnection(string connectionString, string dbName) { var probeTask = Task.Run(() => { var isAlive = false; var client = new MongoDB.Driver.MongoClient(connectionString); for (var k = 0; k < 6; k++) { client.GetDatabase(dbName); var server = client.Cluster.Description.Servers.FirstOrDefault(); isAlive = (server != null && server.HeartbeatException == null && server.State == MongoDB.Driver.Core.Servers.ServerState.Connected); if (isAlive) { break; } System.Threading.Thread.Sleep(300); } return isAlive; }); probeTask.Wait(); return probeTask.Result; }
这背后的想法是MongoDB服务器没有做出反应(并且似乎不存在),直到真正尝试访问服务器上的某些资源(例如数据库)。 但仅检索一些资源是不够的,因为服务器的服务器的Cluster Description中的状态仍然没有更新。 当再次检索资源时,首先进行此更新。 从这个时间点开始,服务器具有有效的集群描述和其中的有效数据......
通常在我看来,MongoDB服务器不会主动将其群集描述传播到所有连接的客户端。 而是,当向服务器发出请求时,每个客户端都会收到描述。 如果你们中的一些人有关于此的更多信息,请确认或否认我对该主题的理解......
现在,当我们定位一个无效的MongoDB服务器URL时,群集描述仍然无效,我们可以捕获并传递此案例的可用信号......
所以以下语句(对于有效的URL)
// The admin database should exist on each MongoDB 3.6 Installation, if not explicitly deleted! var isAlive = ProbeForMongoDbConnection("mongodb://localhost:27017", "admin"); Console.WriteLine("Connection to mongodb://localhost:27017 was " + (isAlive ? "successful!" : "NOT successful!"));
将打印出来
连接到mongodb:// localhost:27017成功了!
和语句(对于无效的URL)
// The admin database should exist on each MongoDB 3.6 Installation, if not explicitly deleted! isAlive = ProbeForMongoDbConnection("mongodb://localhost:27071", "admin"); Console.WriteLine("Connection to mongodb://localhost:27071 was " + (isAlive ? "successful!" : "NOT successful!"));
将打印出来
连接到mongodb:// localhost:27071不成功!
这里有一个ping mongodb服务器的简单扩展方法
public static class MongoDbExt { public static bool Ping(this IMongoDatabase db, int secondToWait = 1) { if (secondToWait <= 0) throw new ArgumentOutOfRangeException("secondToWait", secondToWait, "Must be at least 1 second"); return db.RunCommandAsync((Command)"{ping:1}").Wait(secondToWait * 1000); } }
您可以像这样使用它:
var client = new MongoClient("yourConnectionString"); var database = client.GetDatabase("yourDatabase"); if (!database.Ping()) throw new Exception("Could not connect to MongoDb");
如果要在程序中处理连接问题,可以使用ICluster.Description
事件。
创建MongoClient
,它将继续在后台尝试连接,直到成功为止。
using MongoDB.Driver; using MongoDB.Driver.Core.Clusters; var mongoClient = new MongoClient("localhost") mongoClient.Cluster.DescriptionChanged += Cluster_DescriptionChanged; public void Cluster_DescriptionChanged(object sender, ClusterDescriptionChangedEventArgs e) { switch (e.NewClusterDescription.State) { case ClusterState.Disconnected: break; case ClusterState.Connected: break; } }