mongodb C# query doesn't respond - c#

I'm trying to get Item from mongodb Server, sometimes its work and after 4-5 attemps its stop resonding in the last row (I can't take out the object out side the query)
any one had it before? what is the right way to take out the object?
var client = new MongoClient(connectionString);
var server = client.GetServer();
var database = server.GetDatabase("myPlaces");
var collection = database.GetCollection<MongoPlace>("Places");
int startDay = int.Parse(Request.QueryString["day"]);
MongoPlace mp = collection.AsQueryable<MongoPlace>().Where(x => x.guid ==
Request.QueryString["id"]).FirstOrDefault();

It's likely you're hitting the default connection pool limit.
As it looks like this is a web application, you shouldn't be opening the client more than once per instance of your web application.
The MongoClient, MongoServer, MongoDatabase and MongoCollection are all thread-safe and generally there should only be one instance of each. (See here for more information).
You'd probably want to do this as the application starts and then maintain the connections statically until the application exits.
In my ASP.NET MVC applications, I usually add a "DatabaseConfig" class that's called in the same way as other app configurations. As an example here's some code I've got in the project I'm currently building using MongoDB (there isn't any error handling yet):
var client = new MongoClient(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
var server = client.GetServer();
DataLayer.Client = client;
DataLayer.Server = server;
var settings = new MongoDatabaseSettings(server, "default");
settings.WriteConcern = WriteConcern.Acknowledged;
DataLayer.Database = DataLayer.GetDatabase(settings);
Then, in Application_Start, I call an Initialize method that contains the code above.
DatabaseConfig.Initialize();

Related

How to track MongoDB requests from a console application

I have a Console Application project written in C# which I've added Application Insights to with the following NuGet packages.
Microsoft.ApplicationInsights
Microsoft.ApplicationInsights.Agent.Intercept
Microsoft.ApplicationInsights.DependencyCollector
Microsoft.ApplicationInsights.NLogTarget
Microsoft.ApplicationInsights.PerfCounterCollector
Microsoft.ApplicationInsights.Web
Microsoft.ApplicationInsights.WindowsServer
Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel
I've configured my InstrumentationKey in the config file and I'm firing up a TelemetryClient on startup using the with the following code:
var telemetryClient = new TelemetryClient();
telemetryClient.Context.User.Id = Environment.UserName;
telemetryClient.Context.Session.Id = Guid.NewGuid().ToString();
telemetryClient.Context.Device.OperatingSystem = Environment.OSVersion.ToString();
Everything is working well except AI is not capturing any requests that get sent to Mongo, I can see requests going off to SQL server in the 'Application map' but no sign of any other external requests. Is there any way that I can see telemetry of requests made to Mongo?
EDIT - Thanks to Peter Bons I ended up with pretty much the following which works like a charm and allows me to distinguish between success and failure:
var telemetryClient = new TelemetryClient();
var connectionString = connectionStringSettings.ConnectionString;
var mongoUrl = new MongoUrl(connectionString);
var mongoClientSettings = MongoClientSettings.FromUrl(mongoUrl);
mongoClientSettings.ClusterConfigurator = clusterConfigurator =>
{
clusterConfigurator.Subscribe<CommandSucceededEvent>(e =>
{
telemetryClient.TrackDependency("MongoDB", e.CommandName, DateTime.Now.Subtract(e.Duration), e.Duration, true);
});
clusterConfigurator.Subscribe<CommandFailedEvent>(e =>
{
telemetryClient.TrackDependency("MongoDB", $"{e.CommandName} - {e.ToString()}", DateTime.Now.Subtract(e.Duration), e.Duration, false);
});
};
var mongoClient = new MongoClient(mongoClientSettings);
I am not familiar with MongoDB but as far as I can tell there is no default support for it when it comes to Application Insights. But that does not mean you cannot do this, it will just involve some more code.
Again, I am not familiar with MongoDB but according to http://www.mattburkedev.com/logging-queries-from-mongodb-c-number-driver/ there is built-in support for logging the generated queries. Now, we only need to hook this up to Application Insights.
Since you already know how to use the TelemetryClient we can use the custom tracking methods provided by that class. See https://learn.microsoft.com/nl-nl/azure/application-insights/app-insights-api-custom-events-metrics for the available custom tracking methods.
All you need to do is to insert some code like this:
telemetryClient.TrackDependency(
"MongoDB", // The name of the dependency
query, // Text of the query
DateTime.Now, // Time that query is executed
TimeSpan.FromSeconds(0), // Time taken to execute query
true); // Indicates success
The class telemetryClient is thread-safe so you can reuse it.
Now, according to the referenced blogpost you should be able to do something like this:
var client = new MongoClient(new MongoClientSettings()
{
Server = new MongoServerAddress("localhost"),
ClusterConfigurator = cb =>
{
cb.Subscribe<CommandStartedEvent>(e =>
{
telemetryClient.TrackDependency(
"MongoDB", // The name of the dependency
e.Command.ToJson() // Text of the query
DateTime.Now, // Time that query is executed
TimeSpan.FromSeconds(0), // Time taken to execute query
true); // Indicates success
});
}
});
Again, I am not familiar with MongoDB but I hope this is a starting point for your imagination on how to adapt it to your needs using your knowledge of MongoDB.
EDIT:
If there is also a CommandCompletedEvent or similar event as opposed to the CommandStartedEvent event you should probably track the dependency there because you should then be able to calculate (or simpel read) the time spent and maybe get the actual value for the success indicator.

C# MongoDB.Driver : How to see if server is connected. GetServer Replacement

GetServer is gone for good. How do i check if the server is connected or even exists?
Example code:
// This server exists
var exists = new MongoClient("mongodb://192.168.2.109:27017");
// This server does not exist
var doesNotExist = new MongoClient("mongodb://194.168.200.129:27017");
// Both states return "Discennected"
var connStateExisting = exists.Cluster.Description.State;
var connStateNotExisting = doesNotExist.Cluster.Description.State;
// GetDatabase("name") works for both without errors.
How can i check if a server can be connected?
The Cluster.Description.State does not update immediately. When i checked, it was updated after roughly 100+ milliseconds. The driver contains a connection pool and it seems to do quite a lot asynchronous.
However, the Cluster-property has a "DescriptionChanged"-event that is fired once the connection is done.
If someone else has any knowledge about connections and timeouts, please share it.

Get MongoCluster Primary with C# Drver

I connect with the following code to a mongo database.
Then i iterated through the server descriptions of the cluster but the state is always "disconnected" but when i look with tools like monogchef i can see that all server are connected and there is one primary and all others are secondaries
var client = new MongoClient(conString);
var db = client.GetDatabase("admin");
foreach (var server in client.Cluster.Description.Servers)
{
Console.WriteLine(server.State); // Always returns disconnected.
}
How can I read who is the primary and when has been the last election?
Just found it.
Have to make a dummy request then i find the data under
server.ReplicaSetConfig.Primary

Scaling out SignalR with SQL Server - is it possible to add messages from an outside service?

I am using SQL Server as a backplane for scaling out my SignalR.
In my scenario there are some services which run on other servers and I need to integrate their working status into my SignalR hub.
I tried as a test running a simple Console application with the SQL server scaleout and publish a message like this:
var config = new SqlScaleoutConfiguration(connectionString);
GlobalHost.DependencyResolver.UseSqlServer(connectionString);
var messageBus = new SqlMessageBus(GlobalHost.DependencyResolver, config);
var message = new Message("TransactionHub", "RegisterClient","{userId:1}");
messageBus.Publish(message);
Can I use the SQLScaleout like this somehow?
If not, is there some other way to do what I am trying to do?
Edit:
I've done as halter73 suggested and it works ok, you have to notice that if you activate a client side function, the parameter you send has to match, ie if the object is "Namespace.ClassName" then you should send an object of the same type exactly.
You should try using GlobalHost.ConnectionManager.GetHubContext instead of publishing to the bus directly. Your code would look something like this:
var context = GlobalHost.ConnectionManager.GetHubContext<TransactionHub>();
context.Clients.All.registerClient(new { userId = 1 });

NHibernate transaction not working properly on Postgres

I have common dll referenced by desktop application and web application. One of the methods creates 3 objects and inserts them into DB within transaction.
However, when I call this method at the same time from web application and desktop application, objects are not inserted 3by3...their order is mixed (1 from desktop application, followed by 1 from web application, etc).
Is my code ok?Is there something to do with mapping, or nhibernate cfg???
Thank you very much in advance.
Notifications not = new Notifications();
not.Notes = applicationName;
not.GeneratedTime = DateTime.Now;
using (var session = SessionManager.OpenSession())
using (var transaction = session.BeginTransaction())
{
// do what you need to do with the session
session.Save(not);
not = new Notifications();
not.Notes = applicationName;
not.GeneratedTime = DateTime.Now;
session.Save(not);
not = new Notifications();
not.Notes = applicationName;
not.GeneratedTime = DateTime.Now;
// do what you need to do with the session
session.Save(not);
transaction.Commit();
}
You are under the incorrect assumption that performing inserts in one transaction will prevent inserts from happening in other concurrent transactions.
This is just not true (unless you use some specific transaction isolation level, exclusively lock the whole table, etc... but let's just say it's not true)

Categories

Resources