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

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.

Related

MongoDB - view failed commands

Are failed commands (inserts, updated, deletes etc.) logged anywhere by Mongo DB?
I'm using the C# driver and some commands fail (e.g. inserts) due to duplicate unique key (enforced by an index), so I want to see in retrospect which documents were being inserted.
I would like to see the raw documents that failed, after the driver serialized them.
By the way, as I understand the Mongo oplog only contains successful commands.
Are failed commands (inserts, updated, deletes etc.) logged anywhere by Mongo DB?
I don't think they are, but maybe I haven't tried hard enough to find them yet.
However, you can log them in the application by setting the ClusterConfigurator on the MongoClientSettings like this
//Build the initial settings from the MongoConnectionString
MongoClientSettings settings = MongoClientSettings.FromConnectionString("MongoConnectionString");
//Subscribe on the following events
settings.ClusterConfigurator += cb =>
{
cb.Subscribe(delegate (CommandStartedEvent startedEvent) { Console.WriteLine($"Started: {startedEvent.Command} with OpId: {startedEvent.OperationId}"); });
cb.Subscribe(delegate (CommandSucceededEvent succeededEvent) { Console.WriteLine($"Succeeded OpId: {succeededEvent.OperationId}"); });
cb.Subscribe(delegate (CommandFailedEvent failedEvent) { Console.WriteLine($"Failed OpId: {failedEvent.OperationId}"); });
};
//Builld a MongoClient with the new Settings
var client = new MongoClient(settings);
This example will only write the commands that are being exected and if which OperationId failed or succeeded.
But from here on you can extend it by keeping track of which command got started and what OperationId it runs on.
For a completed example you can see this Gist (as it seems like too much code to post here).
Which can be called as this:
var settings = MongoClientSettings.FromConnectionString("MongoConnectionString");
new MongoTracking().ConfigureTracking(settings);
var client = new MongoClient(settings);
For the record, this does the logging in the application and not the database.

Is it possible to have more than one parse client configured in a single app?

So I have a few different parse servers setup.
One server is just to capture error logs from various applications (I have a LOT out there) in nice uniformed database.
So I might have a specific standalone data migration tool that if it encounters an error, will write out the exception into this Error_log parse table/class. No problem there.
But, if I have an app that uses a Parse Database for itself, I have not been able to figure out how to let it work on it's own parse server configuration for it's own stuff, but write out error logs to this other Parse server instance.
Yes... I could go through the trouble of writing out something via the REST api just for writing out logs,but I am I trying to avoid that and stick with native parse APIs for the particular platform I am on because of the benefits that the APIs give over REST (like save eventually for the none .NET stuff).
EDIT
Some clarification was requested so here I go...
On the app side of things (c# for this example but the same holds true for iOS etc)… I do the usual initialization of the Parse client as such …
ParseClient.Initialize(new ParseClient.Configuration
{
ApplicationId = "MyAppID",
WindowsKey = "MyDotNetKey",
Server = "www.myparseserver.com/app1"
});
So for all calls to save a parse object go through that parse client connection
But what I need to do would be something like this ….
//Main App cloud database
ParseClient1.Initialize(new ParseClient.Configuration
{
ApplicationId = "MyAppID",
WindowsKey = "MyDotNetKey",
Server = "www.myparseserver.com/app1"
});
ParseClient2.Initialize(new ParseClient.Configuration
{
ApplicationId = "MyAppID",
WindowsKey = "MyDotNetKey",
Server = "www.myparseserver.com/errorcollection"
});
try{
ParseConfig config = null;
config = await ParseConfig.GetAsync().ParseClient1;
} catch (Exception ex){
ParseObject MyError = new ParseObject("Error_Log");
MyError["Application"] = "My First App-App2";
MyError["Error"] = ex.message;
await MyError.Save().ParseClient2;
}
Yes - this is all fake code... my point is I want to be able to have multiple ParseClient instances in one app.
Now... I can simply write a routine that writes out errors that resets the ParseClient.Initialization to the error parse server instance and then redo it back to the original (primary app data) instance when it's done... but that is just asking for trouble in a multi threaded environment and will cause conflicts if some other thread in the app goes to write out parse data right at the moment the error method resets the init.
If ParseClient were IDisposable I could probably do that using :
ParseClient ParseErrorServer = new ParseClient();
ParseErrorServer.ApplicationId = "hmmm";
ParseErrorServer.WindwosKey= "hmmm";
ParseErrorServer.Server= "www.hmmm.com/errorcollection";
using ParseErrorServer {
//Do The Work
}
Is that clear as mud yet? ;P
Without alteration I believe none of the Parse SDKs have the ability to initialise multiple instances.
In the iOS SDK for example, is possible to make a new instance (say with a different server url) upon restarting the app but you cannot have multiple. There has also been discussion on the iOS SDK about being able to change the configuration without restart but no one has implemented this yet.
We would happily review a PR for this, however it would require a major and complex overhaul as you would have to manage cache, users etc across multiple instances.

Microsoft Dynamics CRM SDK CRMServiceClient connection string cache bug

Caching behavior of the last Dynamics SDK is driving me crazy.
First, if you want to use CrmServiceClient to access different environments you have to use the parameter RequireNewInstance=True; in the connection string. If not, every instance of CrmServiceClient will use the same connection, even if you create and dispose instances to different environments.
Now, even if you use the RequireNewInstance=True; in the connection string I found that cache still occurs in some scenarios.
var client1 = new CrmServiceClient("RequireNewInstance=True;
Url=https://myCompany.crm.dynamics.com;
Username=myUser#myCompany.onmicrosoft.com; Password=myPassowrd;
AuthType=Office365");
//Now, client 2 points to a url that doesn’t exists:
var client2 = new CrmServiceClient("RequireNewInstance=True;
Url=https://xxx.crm.dynamics.com; Username=myUser#myCompany.onmicrosoft.com;
Password=myPassowrd; AuthType=Office365");
The client2 keeps using the first connection string, so you cannot determine if the new connection string is correct.
Any ideas how to test Dynamics Crm connections strings correctly in my asp.net application?
Late reply, but the behavior you're seeing is because when you're specifying an erroneous URL the discovery service is used to ascertain which instance to connect to.
To prevent this specify SkipDiscovery=True in your connection string:
var connectionString2 = #"AuthType=Office365;Url=https://FAKE.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;SkipDiscovery=True;";
Edit: SkipDiscovery is true by default starting with 9.0.7, kudos to #mwardm
I think I found the problem. It seems to only happens on Dynamics 365 online trials, that was the reason we were getting inconsistent results depending on the environment.
Apparently, the url doesn't need to be completely valid to establish a connection to a CRM online trial environment, as long as the credentials are valid and the url structure is kept.
Let's consider the following example:
var client1 = new CrmServiceClient("RequireNewInstance=True;
Url=https://fake.crm.dynamics.com;
Username=myUser#myCompany.onmicrosoft.com; Password=myPassowrd;
AuthType=Office365");
In this case I can substitute the "fake" part of the url with whatever I want, but still execute requests correctly using the CrmServiceClient service.
If I try to do this with another environment (e.g. 2015, on premise, not-trial crm online, etc.), the IsReady property of the CrmServiceClient would return false and I would get an error in the LastCrmError property.
Very weird behavior, and difficult to pinpoint.
Now that I think I understand the inconsistent behavior I know that finally it will not affect our clients, so I will mark this response as the answer even if I still do not know why we have different behavior between a trial and a normal environment..
I agree choosing to reuse the existing connection if you don't include RequireNewInstance=true seems counter-intuitive, but I can't reproduce what you're seeing. If I try the following from LinqPad crmSvcClient2 will print out errors and then throw a null ref on the Execute call (8.2.0.2 version of the SDK). With this version of the SDK you'll want to always check LastCrmError after connecting to see if the connection failed.
var connectionString = #"AuthType=Office365;Url=https://REAL.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;";
var connectionString2 = #"AuthType=Office365;Url=https://FAKE.crm.dynamics.com;Username=USERNAME;Password=PASSWORD;RequireNewInstance=True;";
using (var crmSvcClient = new CrmServiceClient(connectionString))
{
"crmSvcClient".Dump();
crmSvcClient.LastCrmError.Dump();
((WhoAmIResponse)crmSvcClient.Execute(new WhoAmIRequest())).OrganizationId.Dump();
crmSvcClient.ConnectedOrgFriendlyName.Dump();
}
using (var crmSvcClient2 = new CrmServiceClient(connectionString2))
{
"crmSvcClient2".Dump();
crmSvcClient2.LastCrmError.Dump();
((WhoAmIResponse)crmSvcClient2.Execute(new WhoAmIRequest())).OrganizationId.Dump();
crmSvcClient2.ConnectedOrgFriendlyName.Dump();
}

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

SQL Server Replication Error

I have a SQL Server 2005 box set up for merge replication to SQL Server CE 3.0. The publication, publisher, distributor and IIS have all been set up.
In my application, I attempt to sync the databases using the following code:
//TODO: Change for production
//***************************
string localDBPath = #"C:\Documents and Settings\Robert\Desktop\MyDB.sdf";
//***************************
SqlCeReplication replicator = new SqlCeReplication();
replicator.InternetUrl = "http://myWebServer/sqlcesa30.dll";
replicator.Publisher = "mySqlServer";
replicator.PublisherDatabase = "myDatabase";
replicator.PublisherSecurityMode = SecurityType.NTAuthentication;
replicator.Publication = "myPublication";
replicator.Subscriber = Dns.GetHostName();
replicator.SubscriberConnectionString = #"Data Source=" + localDBPath;
try
{
// Check if the database file already exists
if (!System.IO.File.Exists(localDBPath))
{
// Add a new subscription and create the local database file
replicator.AddSubscription(AddOption.CreateDatabase);
}
// Transfer the initial snapshot of data if this is the first time this is called.
// Subsequent calls will transfer only the changes to the data.
replicator.Synchronize();
}
catch (SqlCeException ex)
{
// Display any errors in message box
MessageBox.Show(ex.Message);
}
finally
{
// Dispose of the SqlCeReplication object, but don't drop the subscription
replicator.Dispose();
}
Unfortunately, this code fails at the "replicator.Synchronize" line with the following error message:
Failure to connect to SQL Server with provided connection information. SQL Server does not exist, access is denied because the IIS user is not a valid user on the SQL Server, or the password is incorrect.
This error message is not very clear to me and I am running out of places to look for the cause of this. Any ideas?
Make sure the agent account is the same user and password on all boxes.
Make sure you are calling the right instances.
Make sure agent is started on all machines involved.
Check the sql event logs on all servers and see which is giving the error, this may also narrow the issue down.
You can also check this to make sure you have setup correctly:
http://msdn.microsoft.com/en-us/library/aa454892.aspx
Same issue here he had to add the instance name correctly:
http://bytes.com/topic/sql-server/answers/611761-merge-replication-error-failure-connect-sql-server-provided-connection
Check these out too:
http://support.microsoft.com/kb/314783
http://support.microsoft.com/kb/319723
http://msdn2.microsoft.com/en-us/library/ms172357.aspx
again make sure you instances are correct:
repl.Publisher = "macnine-name\instance-name"
You can also take a look through this blog:
http://blogs.msdn.com/sql_protocols/archive/2005/09/28/474698.aspx
the message comes from your IIS replication plug-in: //myWebServer/sqlcesa30.dll. When it tries to connect to the publisher, it cannot find it. The publisher is named 'mySqlServer', but apparently it cannot be reached by myWebServer. This can be a name issue (a typo), a firewall issue (SQL port blocked), an IPSEC issue, a configuration issue (SQL is not listenning for remote connections) and so on. Follow normal SQL Server connectivity troubleshooting steps between myWeServer and mySqlServer.

Categories

Resources