Does mongodb C# driver make server call to get database? - c#

I am using mongodb c# driver v2.7.3.
I would like to know if client.GetDatabase() statement makes a call to mongodb server or not?
IMongoClient client = this.dbConnection.client;
var db = client.GetDatabase(databaseName);
Does it internally goes to the mongod shell and run use db command ?
I have many concurrent requests to get the instance of IMongoDatabase. If the driver is making a server call then it would be good if I cache the instance to improve performance.
Looking at the source code, it does not seem that it is making a server call.
But how can I confirm ?
Mongo Db Source Gitlab

If you refer to the Mongo C# Driver references, you'll see a couple of notes.
MongoClient Re-Use
It is recommended to store a MongoClient instance in a global place, either as a static variable or in an IoC container with a singleton lifetime.
However, multiple MongoClient instances created with the same settings will utilize the same connection pools underneath. Unfortunately, certain types of settings are not able to be compared for equality. For instance, the ClusterConfigurator property is a delegate and only its address is known for comparison. If you wish to construct multiple MongoClients, ensure that your delegates are all using the same address if the intent is to share connection pools.
IMongoDatabase Re-use
The implementation of IMongoDatabase provided by a MongoClient is thread-safe and is safe to be stored globally or in an IoC container.
For more info about storing instances and other use cases, you can look at http://mongodb.github.io/mongo-csharp-driver/2.9/reference/driver/connecting/

Until you interact with the MongoClient or the IMongoDatabase instance the connection is not actually established or validated. If you will be using a singleton to store your client instance a test similar to the following could be used:
try
{
_client = new MongoClient(settings);
_database = _client.GetDatabase(db.DatabaseName);
_database.RunCommand((Command<BsonDocument>)"{ping:1}");
}
catch
{
// there is a problem with the settings do not store
}
The above sends a ping command which can be used to test if the server is responding to commands. It will also force the connection to be established via the MongoClient and ensure the connection is valid as a result.

Related

Should C# ClientWebSocket be declared static or instance?

I am currently creating a .NET6 C# trading API client application and the API has two different WebSocket endpoints.
I'm wondering whether the ClientWebSocket object (System.Net.WebSockets) should be declared static or instance. I'm aware HttpClient should be declared static to prevent unnecessary new connections so I'm wondering if the same rationale applies to ClientWebSocket.
From my testing so far my impression is that the ClientWebSocket should be connected and disconnected manually as required, opposed to leaving it connected without any requirement (i.e. just pinging and ponging), and therefore instance objects may be fine to use. Put another way: if websocket connections are explicitly managed there does not appear to be an issue of 'connection re-use' like HttpClient and therefore instances are ok.
Having said that, another design option might be to declare the ClientWebSocket as static and just maintain an open connection + auto re-connect as long as the application is running.
My current design is to have two instance objects of ClientWebSocket, one for each API endpoint. They will be newed up each time a connection is needed.
Any thoughts appreciated.

Properly shutting down MongoDB database connection from C# 2.1 driver?

I am just getting started with integrating MongoDB into my application and I have ran into a few questions. In my application I am using the newest 2.1 version of the MongoDB C# driver and only using MongoDB for application logging.
Currently before showing my main application Form I first check to see if mongod.exe is running and if not I start it. Then when my main Form is shown it opens a connection to the database for use seen below.
public void Open()
{
Client = new MongoClient("mongodb://localhost:27017");
Database = Client.GetDatabase(DBName);
Collection = Database.GetCollection<BsonDocument>(ColName);
}
My question is how I should properly shutdown this connection when my application is closing?
Also are there in considerations I should take into account in leaving mongod.exe running versus exiting it each time the application closes?
I have searched a few times trying to figure out if there is a proper way to shutdown the connection but have found nothing very specific. There is an old SO post (that I can't seem to find now) mentioning a .Dispose method, though I cannot seem to find it in the newest driver nor from my IDE's auto complete.
As of today's version of MongoDB (v2.0.1.27 for MongoDB.Driver), there's no need to close or dispose of connections. The client handles it automatically.
From the docs:
A MongoClient object will be the root object. It is thread-safe and is all that is needed to handle connecting to servers, monitoring servers, and performing operations against those servers.
[...]
It is recommended to store a MongoClient instance in a global place, either as a static variable or in an IoC container with a singleton lifetime. However, multiple MongoClient instances created with the same settings will utilize the same connection pools underneath.
There's a partial/old list of thread-safe MongoDB classes in this SO answer.
The question seems to have been already kinda asked here at When should i be opening and closing MongoDB connections?
If it's accepted answer,
I would leave the connection open as re-creating the connection is
costly. Mongo is fine with lots of connections, open for a long time.
What you ideally should do is to share the connection with all parts
of your application as a persistent connection. The C# driver should
be clever enough to do this itself, so that it does not create too
many connections, as internally it uses "connection pooling" that
makes it even re-use connections. The docs say: "The connections to
the server are handled automatically behind the scenes (a connection
pool is used to increase efficiency)."
works fine for you then all well and good. Even the MongoDB C# driver's quick tour page lends the same advice -
Typically you only create one MongoClient instance for a given cluster
and use it across your application. Creating multiple MongoClients
will, however, still share the same pool of connections if and only if
the connection strings are identical.
Otherwise, I think you can simply put your call to create the connection in a using(){} code block. It automatically calls the dispose method for you (as it implements the IDisposable pattern). You should use this block for any resource you want disposed.
From my experience, the correct way is as answered, but even following these recommendations, I still was having random EndOfStreamException. It seems that some problems are caused by the internet provider closing the connection after some time.
I Solved it by adding:
MongoClientSettings settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
settings.SslSettings = new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
settings.MaxConnectionIdleTime = TimeSpan.FromSeconds(30);

MongoClient GetServer/GetDatabase best practise with ReplicaSet

When should I call MongoClient.GetServer() and MongoServer.GetDatabase()?
Previously I was creating a single MongoDatabase instance at startup and using that for all operations. The problem is that when failover occurs, the primary becomes a different node, making the instance incorrect.
Should I call myClient.GetServer().GetDatabase(myDatabaseName) for every operation? This is probably the most correct, although some calls will fail during failover anyway. I'm tempted to reuse the same database instance for at least a group of operations.
My main concern is that calling GetServer() and GetDatabase() frequently will introduce overhead. I'm sure the driver will use the connection pool and hope that it will do caching of instances, but I do not know when it will have to talk to the server.
You should have one MongoClient representing your abstract connection to the database, one GetServer() call to instantiate a MongoServer instance with a given set of options, and one GetDatabase() call to instantiate a MongoDatabase instance. For the same set of options, you shouldn't need multiple instance of these objects.
It seems like the root cause of this question is failover hndling. The driver should discover the whole replica set and connect to the primary automatically. When failover occurs, there's a period where there is no primary as the election happens, but then the driver should connect to the new primary and resume normal operation. Your client code should be able to handle the failover period, in whatever way is appropriate for your application. The failover won't invalidate your MongoClient, MongoServer, or MongoDatabase instances.

Permanent connection to cassandra or connection per request?

I'm right now implementing my own UserStore for WebApi 2 so it works with cassandra. My question is, if i should close the connection after a request and reconnect to cassandra for the next request.
Right now i am establishing the connection at startup of the application and passing a cassandra Context to the UserStore to work with. the connection is closed when i shut down the application.
I'm wondering if e.g. 10 people register at the same, is this possible with only one connection?
static Startup()
{
PublicClientId = "self";
//Connecting to Cassandra
Cluster cluster = Cluster.Builder().AddContactPoint("127.0.0.1").Build();
Session session = cluster.Connect();
Context context = new Context(session);
//passing context
UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
}
//UserStore Method for Registration
public virtual Task CreateAsync(TUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
var usertable = _context.GetTable<TUser>("users");
//insert user into table
}
When you are deciding if you should have connection pooling or not, there is typically 2 questions you need to answer:
What is the cost of establishing connection every time?
Establishing connection on some networks like EC2 is more expensive depending on the type of network and machines and your architecture setup. It can take several milliseconds and that adds up to your query time if you are establishing connections every time. If you care about saving those milliseconds, then pooling connections is a better option for you.
Connections to databases are resources managed by your OS that your Application Server and DB server are holding onto while being consumed or sleeping. If your hardware resources are low, the connections should be treated like files. You open them, read from, or write to them, then close them. If you don't have hardware resource constraints then don't worry about pooling resource.
On the Cassandra side if you set your rpc_server_type to sync, then each connection will have its own thread which takes minimum of 180K and if you have a lot of clients, then memory will be your limiting factor. If you chose hsha as rpc_server_type, then this won't be a problem.
Read this: https://github.com/apache/cassandra/blob/trunk/conf/cassandra.yaml#L362
About your application performance:
Ideally if you are using Cassandra with a multi-node setup, you want to distribute your requests to multiple nodes (coordinators) so that it scales better. Because of this it is better if you don't stick with the same connection as you will always be talking to the same co-ordinator.
Secondly, if you are multi-threading, you want to make sure your connection is sticking with the same thread while being used for the duration of each query to Cassandra, otherwise, you may end up with race conditions where one thread is updating resources of the connection which is already being used (e.g. trying to sent query packets to server, when it previously was waiting for a response from server).
I recommend implementing a thread-safe connection pool and open several connections on startup of your application and randomly use them for each of your requests, and kill them when your application server stops. Make sure you consider changing the rpc_server_type in Cassandra if you have hardware constraints.
The DataStax C# driver already provides connection pooling internally, thus the recommended way to use the driver is to use a Cluster instance per your C* cluster and a Session per keyspace.Basically initialize these at the startup of your app (nb you can also prepare the PreparedStatements too), reuse these across request, and close them for cleanup when stopping the app (for upgrading, etc).
I'd strongly recommend you to give a quick read of the C# driver docs. It shouldn't take you long and you'll know more about what's included in the driver.

What is the right way to manage MongoDB connections in ASP.Net MVC?

What is the best practice for managing the MongoServer class life cycle? Should I create one and close it at the end of each request or should it be kept as a singleton for the entire life of the app using something like StructureMap?
Any help is appreciate.
In the official documentation it is stated that MongoServer, MongoDatabase, and MongoCollection are thread safe, and that you're supposed to create one single MongoServer for each database that you connect to.
Thus, MongoServer, MongoDatabase, and MongoCollection can safely be configured to be singletons. MongoServer will even help enforcing this by returning the same MongoDatabase instance for successive calls, and MongoDatabase will do the same thing for MongoCollections.
I.e. your MongoServer instance can safely be configured to have a singleton lifestyle in your IoC container, and you might as well set up injection for MongoDatabase and maybe even MongoCollection as well.
I'm using this strategy with Windsor myself - you can see my MongoInstaller here: https://gist.github.com/2427676 - it allows my classes to just go ahead and do this:
public class SomeClass
{
public SomeClass(MongoCollection<Person> people)
{ ... }
}
in order to have a collection injected, nice and ready to use.
The C# driver manages connections to the server automatically (it uses a connection pool). There is no need to call server.Connect as the driver connects automatically. Don't call server.Disconnect as that closes all connections in the connection pool and interferes with efficient connection pooling.
As far as managing the lifecycle of the MongoServer instance you are free to store it in a static variable and use it for the lifetime of your process (and share it across threads, it is thread-safe). Alternatively, you can just call MongoServer.Create again whenever you need to get the server instance. As long as you keep calling MongoServer.Create with the same connection string you will keep getting back the same MongoServer instance.
Inject it using any IOC container (structuremap, Windsor etc.) and keep its lifetime to be on per request basis.

Categories

Resources