How to get the Mongo database specified in connection string in C# - c#

I would like to connect to the database specified in the connection string, without specifying it again in GetDatabase.
For example, if I have a connection string like this;
mongodb://localhost/mydb
I would like to be able to db.GetCollection("mycollection") from mydb.
This would allow the database name to be configured easily in the app.config file.

Update:
MongoServer.Create is obsolete now (thanks to #aknuds1). Instead this use following code:
var _server = new MongoClient(connectionString).GetServer();
It's easy. You should first take database name from connection string and then get database by name. Complete example:
var connectionString = "mongodb://localhost:27020/mydb";
//take database name from connection string
var _databaseName = MongoUrl.Create(connectionString).DatabaseName;
var _server = MongoServer.Create(connectionString);
//and then get database by database name:
_server.GetDatabase(_databaseName);
Important: If your database and auth database are different, you can add a authSource= query parameter to specify a different auth database. (thank you to #chrisdrobison)
From docs:
NOTE If you are using the database segment as the initial database to
use, but the username and password specified are defined in a
different database, you can use the authSource option to specify the
database in which the credential is defined. For example,
mongodb://user:pass#hostname/db1?authSource=userDb would authenticate
the credential against the userDb database instead of db1.

In this moment with the last version of the C# driver (2.3.0) the only way I found to get the database name specified in connection string is this:
var connectionString = #"mongodb://usr:pwd#srv1.acme.net,srv2.acme.net,srv3.acme.net/dbName?replicaSet=rset";
var mongoUrl = new MongoUrl(connectionString);
var dbname = mongoUrl.DatabaseName;
var db = new MongoClient(mongoUrl).GetDatabase(dbname);
db.GetCollection<MyType>("myCollectionName");

With version 1.7 of the official 10gen driver, this is the current (non-obsolete) API:
const string uri = "mongodb://localhost/mydb";
var client = new MongoClient(uri);
var db = client.GetServer().GetDatabase(new MongoUrl(uri).DatabaseName);
var collection = db.GetCollection("mycollection");

The answer below is apparently obsolete now, but works with older drivers. See comments.
If you have the connection string you could also use MongoDatabase directly:
var db = MongoDatabase.Create(connectionString);
var coll = db.GetCollection("MyCollection");

Related

Change DBase On Run Time C# app

I have developed an accounting program that is working beautifully, but now a new need has arisen.
When I enter the program, by default it reads the DB that I put in the file WinSCM.exe.config and if I want to change I have to exit the program and edit the file changing the DB name.
I did not want it to be this way, because my client does accounting for several companies and each company is a DB, so I wanted a way to select a company and when selecting this company the database is automatically changed in the release version.
I'm using Entity Framework to connect to Sql Server DB
Can someone help me?
I'm not sure what reading your DB is, but normally when you use Entity Framework you create a DbContext object whenever you need to do a query, or at utmost a few queries. You are not supposed to keep this DbContext alive for longer periods of time, say more than a few seconds. A minute would be very rare.
Whenever you create the Dbcontext instance you could use the default constructor that uses the config file to get the connection string to the database.
However one of the other constructors let you define the connection string to the database in the constructor. So if you want to construct your DbContext and connect it to a different database, just use that constructor
If you don't know the connection string, but you have a DbConnection to the database, there will be even a constructor for this case.
Hi Everybody Thank alot for your Answer. I just Solved My Question like this:
Fisrt of all, I created a class wich I called ConnetionTolls with this Content://.
public static class ConnectionTools
{
// all params are optional
public static void ChangeDatabase(
this DbContext source,
string initialCatalog = "",
string dataSource = "",
string userId = "",
string password = "",
bool integratedSecuity = true,
string configConnectionStringName = "")
/* this would be used if the
* connectionString name varied from
* the base EF class name */
{
try
{
// use the const name if it's not null, otherwise
// using the convention of connection string = EF contextname
// grab the type name and we're done
var configNameEf = string.IsNullOrEmpty(configConnectionStringName)
? source.GetType().Name
: configConnectionStringName;
// add a reference to System.Configuration
var entityCnxStringBuilder = new EntityConnectionStringBuilder
(System.Configuration.ConfigurationManager
.ConnectionStrings[configNameEf].ConnectionString);
// init the sqlbuilder with the full EF connectionstring cargo
var sqlCnxStringBuilder = new SqlConnectionStringBuilder
(entityCnxStringBuilder.ProviderConnectionString);
// only populate parameters with values if added
if (!string.IsNullOrEmpty(initialCatalog))
sqlCnxStringBuilder.InitialCatalog = initialCatalog;
if (!string.IsNullOrEmpty(dataSource))
sqlCnxStringBuilder.DataSource = dataSource;
if (!string.IsNullOrEmpty(userId))
sqlCnxStringBuilder.UserID = userId;
if (!string.IsNullOrEmpty(password))
sqlCnxStringBuilder.Password = password;
// set the integrated security status
sqlCnxStringBuilder.IntegratedSecurity = integratedSecuity;
// now flip the properties that were changed
source.Database.Connection.ConnectionString
= sqlCnxStringBuilder.ConnectionString;
}
catch (Exception ex)
{
// set log item if required
}
}
********the way to use it is like this***************
//I use this method in a diferent Class
//This method returns the Entity i use with new connections
public static MyEntities SelectDb(String DataBase,String sqlUser,String pw, String serverInstance){
var selectedDbase = new MyEntities();
// so only reference the changed properties
// using the object parameters by name
selectedDbase.ChangeDatabase
(
initialCatalog: DataBase,
userId: sqlUser,
password: pw,
dataSource: serverInstance// could be ip address 100.23.45.67 etc
);
return selectedDbase;
}
I want to thank everyone here and on other forums because this was the result of Your Contributions

Create ASB MessagingFactory from connection string and provide settings

I want to create an Azure Service Bus MessagingFactory instance from a connection string and specific the BatchFlushInterval setting.
The factory method on MessagingFactory that takes a connection string does not take a MessagingFactorySettings instance.
The factory method on MessagingFactory that takes a MessagingFactorySettings instance does not take a connection string.
The closest I've come is this:
var connectionStringBuilder = new ServiceBusConnectionStringBuilder(connectionString);
var messagingSettings = new MessagingFactorySetttings
{
TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(connectionStringBuilder.SharedSecretIssuerName, connectionStringBuilder.SharedSecretIssuerSecret),
NetMessagingTransportSettings =
{
BatchFlushInterval = TimeSpan.FromMilliseconds(100) // <-- This is the setting I want to specify.
}
};
var messagingFactory = MessagingFactory.CreateFromConnectionString(connectionStringBuilder.Endpoints, messagingSettings);
But that only works if you know that's the specific token provider information provided in the connection string. If it does something else, like use one of the other five methods of providing tokens, then this code fails.
How can you create a MessagingFactory instance from a connection string and specify the BatchFlushInterval?
The way I found to do it is by using the token provider from the namespace manager. So:
var namespaceMngr = NamespaceManager.CreateFromConnectionString(namespaceConnString);
MessagingFactorySettings mfs = new MessagingFactorySettings();
mfs.TokenProvider = namespaceMngr.Settings.TokenProvider;
mfs.NetMessagingTransportSettings.BatchFlushInterval = TimeSpan.FromSeconds(timeToFlush);
MessagingFactory mf = MessagingFactory.Create(namespaceMngr.Address, mfs);
If you are trying to set the AmqpTransportSettings.BatchFlushInterval instead of the NetMessagingTransportSettings.BatchFlushInterval then I can't help you, I actually stumbled on this post looking for an answer. Trying to change the AmqpTransportSettings.BatchFlushInterval doesn't seem to stick to the MessageFactory even if the MessageFactorySettings reflect the change.
JordanSchillers answer fixes the token provider issue but my address was now using port 9355 instead of 9354.
I ended using a mixture of the ServiceBusConnectionStringBuilder and the NamespaceManager:
var serviceBusConnectionString = new ServiceBusConnectionStringBuilder(connection.ConnectionString);
MessagingFactorySettings factorySettings = new MessagingFactorySettings();
factorySettings.TransportType = serviceBusConnectionString.TransportType;
//Use the namespacemanager to create the token provider.
var namespaceManager = NamespaceManager.CreateFromConnectionString(connection.ConnectionString);
factorySettings.TokenProvider = namespaceManager.Settings.TokenProvider;
factorySettings.NetMessagingTransportSettings.BatchFlushInterval = TimeSpan.FromMilliseconds(batchTimeInMs);
MessagingFactory factory = MessagingFactory.Create(serviceBusConnectionString.Endpoints, factorySettings);
return factory.CreateTopicClient(topicName);

MVC inject DataAccessLayer based on the logged in user

I've an application which insert/save data in different databases hosted on different server. UI may be different but at the end data which is getting saved is almost same.
So i want to use the same DataAccessLayer but want to change the connectionString based on the loggedin user.
Dependency can be configured in startup.cs but at that time i may not know the DataBase user would like to work with.
on login page i'm asking user to select the database to work with, so only way to change the connection string is after login page.
Any suggestion?
public class ConnectionRepository : IConnectionRepository
{
private IDbConnection _cnn = null;
public IDbConnection GetOpenConnection(string databaseName)
{
if (_cnn != null && _cnn.ConnectionString.ToLower().Contains(databaseName.ToLower()))
{
_cnn.Open();
return _cnn;
}
var cnn = ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString();
//Now replace database name in connection string with whichever one supplied
var cb = new SqlConnectionStringBuilder(cnn) { InitialCatalog = databaseName };
// wrap the connection with a profiling connection that tracks timings
return new ProfiledDbConnection(new SqlConnection(cb.ConnectionString), MiniProfiler.Current);
}
}
This code replaces the InitialCatalog (database name) part of the connection string dynamically base on the supplied name. The current name is stored in session when the user logs in.
Hope this helps.

Assign Credentials (user name/password) to EF in Code

I have my entity model and connection set up, and as you probably know when you set up the connection to be stored in the config file, it recommends you don't store the "sensitive" data (i.e. user name and password) in the config file, well what I wanted to do was allow the user to enter that information themselves.
How do I assign it to the connection in code?
Do I have to pull the string, modify it (by adding the user/pass) and then reassign the connection string?
sounds like a desktop (not a web app), correct? since you are probably not running over the internet but rather in a local network why don't you use integrated (windows) security instead of the sql server security and hot have to store the login/password at all.
public class MyContext : DbContext
{
// Add a constructor that takes a connection string
public MyContext(string connString)
: base(connString)
{
}
}
// Call this method from a page or controller
public void ConnectToTheDatabase(string username, string password)
{
// create the connection string; I like to user the builder
System.Data.Common.DbConnectionStringBuilder builder
= new System.Data.Common.DbConnectionStringBuilder();
builder.Add("Server", "tcp:asdfewsdfgwe.database.windows.net,1422");
builder.Add("Database", "supersonic_db");
builder.Add("User ID", username);
builder.Add("Password", password);
builder.Add("Trusted_Connection", "False");
builder.Add("Encrypt", "True");
builder.Add("Connection Timeout", "30");
var connString = builder.ToString();
// Set the connection string
MyContext context = new MyContext(connString);
// Test with something simple
context.Database.Connection.Open();
string version = context.Database.Connection.ServerVersion;
version = version.ToUpper();
}

How to create a new Mongo Database programatically?

I'm trying to create a new database programatically, kind'a one database per client.
and using this:
public void CreateNewClientDatabase(Client client)
{
var connectionString = Util.GetClientDatabaseConnectionString(client.DatabaseName);
var mongoClient = new MongoDB.Driver.MongoClient(connectionString);
var server = mongoClient.GetServer();
var db = server.GetDatabase(client.DatabaseName);
db.CreateCollection("DatabaseCreated");
}
The Error I'm getting on CreateCollection is that I do not have the correct credentials, even though that in the connection string, my credentails are correct.
The Exception reads as:
Invalid credentials for database 'client_database_name'.
and the InnerException as:
{"Command 'authenticate' failed: auth fails (response: { \"errmsg\" : \"auth fails\", \"ok\" : 0.0 })"}
The connectionString ends up being this:
mongodb://admin_user:admin_pwd#linus.mongohq.com:10042/client_database_name
What am I missing?
P.S. Using version 1.7 of MongoDB Driver
Bruno ... to do this on a shared service like MongoHQ, you will need to use their API to create new databases programmatically. Docs for the API are located at: http://support.mongohq.com.

Categories