如何检查与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; } }