Jacobian
Jacobian

Reputation: 10872

How to check connection to mongodb

I use MongoDB drivers to connect to the database. When my form loads, I want to set up connection and to check whether it is ok or not. I do it like this:

var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("reestr");

But I do not know how to check connection. I tried to overlap this code with try-catch, but to no avail. Even if I make an incorrect connectionString, I still can not get any error message.

Upvotes: 41

Views: 80935

Answers (8)

Ron B Palmer
Ron B Palmer

Reputation: 39

If you are just checking for testing and terminal output will do the trick then try this where usersCollection is the full client string to the database and the collection:

console.log(usersCollection); usersCollection.insertOne(this.data);

You should see something like this in the terminal:

Collection {
  s: {
    db: Db { s: [Object], client: [MongoClient] },
    options: {
      raw: false,
      useBigInt64: false,
      promoteLongs: true,
      promoteValues: true,
      promoteBuffers: false,
      ignoreUndefined: false,
      bsonRegExp: false,
      serializeFunctions: false,
      fieldsAsRaw: {},
      enableUtf8Validation: true,
      readPreference: [ReadPreference]
    },
    namespace: MongoDBCollectionNamespace {
      db: 'ComplexApp',
      collection: 'users'
    },
    pkFactory: { createPk: [Function: createPk] },
    readPreference: ReadPreference {
      mode: 'primary',
      tags: undefined,
      hedge: undefined,
      maxStalenessSeconds: undefined,
      minWireVersion: undefined
    },
    bsonOptions: {
      raw: false,
      useBigInt64: false,
      promoteLongs: true,
      promoteValues: true,
      promoteBuffers: false,
      ignoreUndefined: false,
      bsonRegExp: false,
      serializeFunctions: false,
      fieldsAsRaw: {},
      enableUtf8Validation: true
    },
    readConcern: undefined,
    writeConcern: undefined
  },
  client: <ref *1> MongoClient {
    _events: [Object: null prototype] {},
    _eventsCount: 0,
    _maxListeners: undefined,
    mongoLogger: MongoLogger {
      error: [Function: bound log],
      warn: [Function: bound log],
      info: [Function: bound log],
      debug: [Function: bound log],
      trace: [Function: bound log],
      componentSeverities: [Object],
      maxDocumentLength: 1000,
      logDestination: [Object]
    },
    s: {
      url: 'mongodb://0.0.0.0:27017/',
      bsonOptions: [Object],
      namespace: [MongoDBNamespace],
      hasBeenClosed: false,
      sessionPool: [ServerSessionPool],
      activeSessions: Set(0) {},
      options: [Getter],
      readConcern: [Getter],
      writeConcern: [Getter],
      readPreference: [Getter],
      isMongoClient: [Getter]
    },
    topology: Topology {
      _events: [Object: null prototype],
      _eventsCount: 26,
      _maxListeners: undefined,
      client: [Circular *1],
      selectServerAsync: [Function (anonymous)],
      s: [Object],
      [Symbol(kCapture)]: false,
      [Symbol(waitQueue)]: [List]
    },
    connectionLock: undefined,
    [Symbol(kCapture)]: false,
    [Symbol(options)]: [Object: null prototype] {
      hosts: [Array],
      compressors: [Array],
      connectTimeoutMS: 30000,
      directConnection: false,
      driverInfo: {},
      enableUtf8Validation: true,
      forceServerObjectId: false,
      heartbeatFrequencyMS: 10000,
      loadBalanced: false,
      localThresholdMS: 15,
      maxConnecting: 2,
      maxIdleTimeMS: 0,
      maxPoolSize: 100,
      minPoolSize: 0,
      minHeartbeatFrequencyMS: 500,
      monitorCommands: false,
      noDelay: true,
      pkFactory: [Object],
      raw: false,
      readPreference: [ReadPreference],
      retryReads: true,
      retryWrites: true,
      serverMonitoringMode: 'auto',
      serverSelectionTimeoutMS: 30000,
      socketTimeoutMS: 0,
      srvMaxHosts: 0,
      srvServiceName: 'mongodb',
      waitQueueTimeoutMS: 0,
      zlibCompressionLevel: 0,
      dbName: 'test',
      userSpecifiedAuthSource: false,
      userSpecifiedReplicaSet: false,
      mongoLoggerOptions: [Object],
      metadata: [Object],
      [Symbol(@@mdb.enableMongoLogger)]: false
    }
  }
}

Upvotes: 0

Phani Bnr
Phani Bnr

Reputation: 23

This is a solution by using the try-catch approach,

var database = client.GetDatabase("YourDbHere");
bool isMongoConnected;
try
{
     await database.RunCommandAsync((Command<BsonDocument>)"{ping:1}");
     isMongoConnected = true;
}
catch(Exception)
{
    isMongoConnected = false;
}    

so when it fails to connect to the database, it will throw an exception and we can handle our bool flag there.

Upvotes: 1

Iannick
Iannick

Reputation: 188

Here a simple extension method to ping mongodb server

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<MongoDB.Bson.BsonDocument>)"{ping:1}").Wait(secondToWait * 1000);
    }
} 

You can use it like so:

var client = new MongoClient("yourConnectionString");
var database = client.GetDatabase("yourDatabase");
if (!database.Ping())
    throw new Exception("Could not connect to MongoDb");

Upvotes: 3

Ramanagom
Ramanagom

Reputation: 329

I've had the same question as the OP, and tried every and each solution I was able to find on Internet... Well, none of them worked to my true satisfaction, so I've opted for a research to find a reliable and responsive way of checking if connection to a MongoDB Database Server is alive. And this without to block the application's synchronous execution for too long time period...

So here are my prerequisites:

  • Synchronous processing of the connection check
  • Short to very short time slice for the connection check
  • Reliability of the connection check
  • If possible, not throwing exceptions and not triggering timeouts

I've provided a fresh MongoDB Installation (version 3.6) on the default localhost URL: mongodb://localhost:27017. I've also written down another URL, where there was no MongoDB Database Server: mongodb://localhost:27071.

I'm also using the C# Driver 2.4.4 and do not use the legacy implementation (MongoDB.Driver.Legacy assembly).

So my expectations are, when I'm checking the connection to the first URL, it should give to me the Ok for a alive connection to an existing MongoDB server, when I'm checking the connection to the second URL it should give to me the Fail for a non-existing MongoDB server...

Using the IMongoDatabase.RunCommand method, queries the server and causes the server response timeout to elapse, thus not qualifying against the prerequisites. Furthermore after the timeout, it breaks with a TimeoutException, which requires additional exception handling.

This actual SO question and also this SO question have delivered the most of the start information I needed for my solution... So guys, many thanks for this!

Now my solution:

    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;
    }

The idea behind this is the MongoDB Server does not react (and seems to be non-existing) until a real attempt is made to access some resource on the server (for example a database). But retrieving some resource alone is not enough, as the server still has no updates to its state in the server's Cluster Description. This update comes first, when the resource is retrieved again. From this time point, the server has valid Cluster Description and valid data inside it...

Generally it seems to me, the MongoDB Server does not proactivelly propagate its Cluster Description to all connected clients. Rather then, each client receives the description, when a request to the server has been made. If some of you fellows have more information on this, please either confirm or deny my understandings on the topic...

Now when we target an invalid MongoDB Server URL, then the Cluster Description remains invalid and we can catch and deliver an usable signal for this case...

So the following statements (for the valid 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!"));

will print out

Connection to mongodb://localhost:27017 was successful!

and the statements (for the invalid 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!"));

will print out

Connection to mongodb://localhost:27071 was NOT successful!

Upvotes: 3

Pav K.
Pav K.

Reputation: 2858

full example for 2.4.3 - where "client.GetServer()" isn't available. based on "Paul Keister" answer.

client = new MongoClient("mongodb://localhost");
database = client.GetDatabase(mongoDbStr);
bool isMongoLive = database.RunCommandAsync((Command<BsonDocument>)"{ping:1}").Wait(1000);

if(isMongoLive)
{
    // connected
}
else
{
    // couldn't connect
}

Upvotes: 29

Scyssion
Scyssion

Reputation: 514

If you want to handle connection issues in your program you can use the ICluster.Description event.

When the MongoClient is created, it will continue to attempt connections in the background until it succeeds.

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;
    }
}

Upvotes: -1

Paul Keister
Paul Keister

Reputation: 13097

To ping the server with the new 3.0 driver its:

var database = client.GetDatabase("YourDbHere");

database.RunCommandAsync((Command<BsonDocument>)"{ping:1}")
        .Wait();

Upvotes: 49

mnemosyn
mnemosyn

Reputation: 46331

There's a ping method for that:

var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var server = client.GetServer();
server.Ping();

Upvotes: 28

Related Questions