How to add Global MongoDB connection String to C# Project - c#

I am using my MongoDB database to store some documents for my project. The driver version for MongoDB I am using is 2.12.2.
How I am using my Mongo connection for my Operations is like this,
Web.config
<configuration>
<appSettings>
<add key="MongoDBDatabase" value="TestDB" />
</appSettings>
<connectionStrings>
<add name="MongoConnection" connectionString="myconnnection/db?retryWrites=true"/>
</connectionStrings>
</configuration>
DBConnection.cs
using System.Configuration;
namespace MyProj.DataAccess.Implementations
{
internal class DBConnection
{
public static string MongoDBConnectionString { get { return ConfigurationManager.ConnectionStrings["MongoConnection"].ConnectionString; } }
public static string MongoDBdatabase { get { return ConfigurationManager.AppSettings["MongoDBDatabase"].ToString(); } }
}
}
UserDAL.cs
namespace MyProj.DataAccess.Implementations
{
public class UserDAL: IUserDAL
{
public static string database = DBConnection.MongoDBdatabase;
public List<UserTbl> GetAll()
{
var con = new MongoClient(DBConnection.MongoDBConnectionString);
var db = con.GetDatabase(database);
var collection = db.GetCollection<UserTbl>("UserTbls");
var users=collection.AsQueryable().ToList();
}
}
}
The thing is I need to call the connection globally like from singleton. So that only a single connection is open for multiple requests. How can I do that ?

I prefer to you to config your mongodb client with best practices like this
you can define your mongodb as singlton but be aware you should use async methods , I prefer you to use ConcurrentQueue and its methods

Related

Change Database on the fly in Entity Framework same scheme

I have a context which I derive my entity I have 5 databases these database are off the same scheme that I need to switch from at run time. The user would be selecting at the launch of the application which database they would be connecting to.
The database that is of the same scheme is SMBASchedulerEntities its just the catalogue name that is different
public class SourceContext : ContextBase
{
public SMBASchedulerEntities _sourceEntities = new SMBASchedulerEntities();
public SystemDa _systemDB = new SystemDa();
public void AddToPatient(Patient newPatient)
{
_sourceEntities.Patients.Add(newPatient);
SaveChanges();
}
public void AddToAppointmentTypes(AppointmentType AppointmentTypes)
{
_sourceEntities.AppointmentTypes.Add(AppointmentTypes);
SaveChanges();
}
}
As you can see there I reference the entities within my context so I would like to have a property that I can call such as changeDatabase and that it would take affect without restarting the application is that at all possible.
You can pass the name of the connection string you want to connect to, when instantiating your DbContext. First, you declare your DbContext like so:
public class SMBASchedulerEntities : DbContext
{
public SMBASchedulerEntities(string connectionString): base(connectionString)
{
}
}
You keep all your connection strings in your Web.config or App.config (depending on the type of project):
<connectionStrings>
<add name="DefaultConnection1" connectionString="server=localhost;user id=MyAppUser;password=SecretPass;database=MyDatabase1" providerName="System.Data.SqlClient" />
<add name="DefaultConnection2" connectionString="server=localhost;user id=MyAppUser;password=SecretPass;database=MyDatabase2" providerName="System.Data.SqlClient" />
<add name="DefaultConnection3" connectionString="server=localhost;user id=MyAppUser;password=SecretPass;database=MyDatabase3" providerName="System.Data.SqlClient" />
<add name="DefaultConnection4" connectionString="server=localhost;user id=MyAppUser;password=SecretPass;database=MyDatabase4" providerName="System.Data.SqlClient" />
<add name="DefaultConnection5" connectionString="server=localhost;user id=MyAppUser;password=SecretPass;database=MyDatabase5" providerName="System.Data.SqlClient" />
</connectionStrings>
Then you use it like this:
using (var db = new SMBASchedulerEntities("DefaultConnection1"))
{
// use MyDatabase1 through connection string "DefaultConnection1"
}
using (var db = new SMBASchedulerEntities("DefaultConnection2"))
{
// use MyDatabase2 through connection string "DefaultConnection2"
}
Dispose your DbContext
It's recommended to dispose the DbContext after using it. If you still want to use your idea with SourceContext, you could implement something like this:
public class SourceContext : ContextBase, IDisposable
{
public SMBASchedulerEntities _sourceEntities;
public SystemDa _systemDB = new SystemDa();
public SourceContext(string connectionString)
{
_sourceEntities = new SMBASchedulerEntities(connectionString);
}
public void AddToPatient(Patient newPatient)
{
_sourceEntities.Patients.Add(newPatient);
SaveChanges();
}
public void ChangeDatabaseTo(string connectionString)
{
if (_sourceEntities != null)
_sourceEntities.Dispose();
_sourceEntities = new SMBASchedulerEntities(connectionString);
}
public void AddToAppointmentTypes(AppointmentType AppointmentTypes)
{
_sourceEntities.AppointmentTypes.Add(AppointmentTypes);
SaveChanges();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_sourceEntities != null)
{
_sourceEntities.Dispose();
}
}
}
}
...then finally use it like this:
using(var context = new SourceContext("DefaultConnection1"))
{
context.AddPatient(patient); // add to Database1
context.ChangeDatabaseTo("DefaultConnection2");
context.AddPatient(patient); // add to Database2
context.ChangeDatabaseTo("DefaultConnection4");
context.AddPatient(patient); // add to Database4
}
By making your SourceContext an IDisposable, you have the opportunity to properly dispose the DbContext instance. Take note I took care of disposing the existing DbContext before changing it.
So, turns out the easiest way to do this is to put all of the DB names and connection strings in the appsettings.json file.
You can make it very complex, of course, but what I did was make a select drop down, let the user select the DB they want to use, then fire the onclick method to pull the connection string out of the app settings.json file, create an instance of the DBCONTEXT with that name’s connection string and use that DB context throughout whatever you need from there.
Public static class AppSettings
{
public static string GetConnectionString(string sDBinstanceName)
{
IConfigurationRoot Configuration;
IConfigurationBuilder builder = new ConfigurationBuilder().SetpathName(<wherever your appsettings.json file is>,”appsettings.json”).ReadJsonFile();
Configuration = builder.Build();
var tmpSettings = Configuration.GeyAppSettings();
string dbConstr = tmpSettings[“ConnectionStrings”][sDBinstanceName];
return dbConstr;
}
}
This is not MY snippet, but a derivative of what I found online. As it is from memory, it is not 100% correct, but I will fix it on Monday. I will update with author when I find it again(Monday).
Once you get the connection string you treat the DBCONTEXT like any other object, create it, use the tables (MEF) and whatever else you need, then destroy it correctly or let the garbage collection clean it up.
I got this working yesterday and please note: There are ZERO DBCONTEXTs registered in the Program.cs file as they are not needed.
This system is simple, lets you allow the user control to which Database they need based on a simple selection mechanism and answers the question.
At our shop we have MULTIPLE databases with exact same schema because we segregate data based on the timeframe for that data, but I can envision situations where you could use different schemas depending on the selection, we just do not do that.
For instance we have a Production and Development DB that are EXACTLY the same schema (different data) so the one DBCONTEXT is used for both in MEF.
With the method above we can let the user see the data in either at their command, it’s just getting there is a whole lot easier.

Simple but good example on how to use Dapper with Structuremap and dependency injection

I am trying to understand how to use Dependency Injection with Dapper (IDbConnection) and still being able to use built in dispose.
I have found a couple of articles on the web but non that I think is easy to understand.
What I am trying to figure out is how to make this simple class be testable:
public class UserProfileRepository : IUserProfileRepository
{
private readonly IConfigRepository _configRepository;
public UserProfileRepository(IConfigRepository configRepository)
{
_configRepository = configRepository;
}
public UserProfile GetUserProfile(string userId)
{
const string query = #"Select UserId, UserName
From Users
Where UserId = #UserId";
using (var conn = new SqlConnection(_configRepository.GetConnectionString("MyConnectionString")))
{
conn.Open();
return conn.Query<UserProfile>(query, new { UserId = userId }).SingleOrDefault();
}
}
}
I have a config repository that looks like this so I can mock the request to web.config away:
public class ConfigRepository : IConfigRepository
{
public string GetConnectionString(string key)
{
var conString = ConfigurationManager.ConnectionStrings[key];
if (conString != null)
{
return conString.ConnectionString;
}
return string.Empty;
}
}
I have read that you could use ConnectionFactory but has not figur out how to implement it and still know I am disposing it correct.
Can anyone point me in the right direction?
Best connection creation mechanism as per my experience is the combination of DependencyInjection and ConnectionFactory. I am getting rid of IConfigRepository, since here all the work is done using factory
Advantages are Multi fold:
Create a connection object at runtime in transaction or thread scope
At runtime change the data provider and thus database of the system ( using Connection Factory)
What you shall do (in Code):
Declare the IDBConnection object in the Data access Layer:
[Inject] // Property Injection
public IDBConnection Connection {get; set;}
Declare the binding using a DI framework like Ninject:
Bind<IDBConnection>().ToMethod(ctx =>
ConnectionFactory.CreateDbConnection("DefaultConnection"));
Create the DBConnection Factory as follows:
Connection factory fetches the Connection provider and connection string from the config file as follows:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=<Value>;Initial Catalog=<Value>;User Id=<Value>;Password=<Value>" providerName="System.Data.SqlClient" />
</connectionStrings>
Identifier is DefaultConnection, which is using the SqlClient provider, but at run time can be changed to the different client like Oracle, MySql
using System;
using System.Data.Common;
public static class ConnectionFactory
{
/// <summary>
/// Create DBConnection type based on provider name and connection string
/// </summary>
/// <param name="connectionIdentifier"></param>
/// <returns></returns>
public static DbConnection CreateDbConnection(string connectionIdentifier)
{
// Provider name setting
var providerNameValue = ConfigurationManager.ConnectionStrings[connectionIdentifier].ProviderName;
// Connection string setting
var connectionStringValue = ConfigurationManager.ConnectionStrings[connectionIdentifier].ConnectionString;
// Assume failure.
DbConnection connection;
// Null connection string cannot be accepted
if (connectionStringValue == null) return null;
// Create the DbProviderFactory and DbConnection.
try
{
// Fetch provider factory
var factory = DbProviderFactories.GetFactory(providerNameValue);
// Create Connection
connection = factory.CreateConnection();
// Assign connection string
if (connection != null)
connection.ConnectionString = connectionStringValue;
}
catch (Exception ex)
{
connection = null;
}
// Return the connection.
return connection;
}
}
How to use it:
For a single call and dispose
using(Connection)
{
...
}
For a Transaction context, use as-is, no using required
Regarding Mocking:
Which ever Mock framework you use for the Unit testing you have to mock the result of the UserProfileRepository :: GetUserProfile(string userId), this would be easier instead of filling a MockConnection using dependency Injection, which will make it complex. DI is good for real use case, for filling connection object at runtime

How to store custom data in web.config?

I have the following method in my apiController:
public IEnumerable<something> GetData(DataProvider dataProvider)
{
return dataProvider.GetData();
}
What I need is to invoke this method from javascript and pass it a parameter of DataProvider derived type. I can handle this by passing string, e.g. "FirstProvider" and than write N number of if's in GetData() method to create an instance of proper type.
But is there some way that I can write in web.config file something like:
<DataProviders>
<type = FirstDataProvider, alias = "FirstProvider">
<type = SecondDataProvider, alias = "SecondProvider">
</DataProviders>
Change getData method to:
public IEnumerable<something> GetData(string dataProviderAlias)
{
// get provider type by it's alias from web congfig,
// then instantiated and call:
return dataProvider.GetData();
}
And then find and instantiate the type by it's alias?
Note: I accepted the answer below cause it's pointed me in a right direction, but msdn says that IConfigurationSectionHandler is deprecated.
So I used ConfigurationSection, ConfigurationElementCollection, ConfigurationElement classes instead to build custom config section.
You can store arbitrary data in web.config in the appSettings element:
<configuration>
<appSettings>
<add key="FirstAlias" value="FirstProvider" />
<add key="SecondAlias" value="SecondProvider" />
</appSettings>
</configuration>
And you can then read the values using:
String firstAlias = System.Configuration.ConfigurationManager.AppSettings["FirstAlias"];
String secondAlias = System.Configuration.ConfigurationManager.AppSettings["SecondAlias"];
It's built-in. It's supported. It's where you're supposed to store custom data.
First of all, you can only store valid xml in web.config. <type = FirstDataProvider, alias = "FirstProvider"> is not valid xml.
Second, there are a lot of moving pieces. Please follow the steps carefully -
web.config
Make sure you enter the proper namespace for DataProviders. type="YOUR_APPLICATION.DataProviders".
<configuration>
<configSections>
<section name="DataProviders" type="WebApplication2010.DataProviders"
requirePermission="false"/>
</configSections>
<DataProviders>
<Provider type="FirstDataProvider" alias="FirstProvider"/>
<Provider type="SecondDataProvider" alias="SecondProvider"/>
</DataProviders>
....
</configuration>
Code
public class DataProviders : IConfigurationSectionHandler
{
private static bool _initialized;
public static List<Provider> _providers;
public object Create(object parent, object configContext, XmlNode section)
{
XmlNodeList providers = section.SelectNodes("Provider");
_providers = new List<Provider>();
foreach (XmlNode provider in providers)
{
_providers.Add(new Provider
{
Type = provider.Attributes["type"].Value,
Alias = provider.Attributes["alias"].Value,
});
}
return null;
}
public static void Init()
{
if (!_initialized)
{
ConfigurationManager.GetSection("DataProviders");
_initialized = true;
}
}
public static IEnumerable<Provider> GetData(string dataProviderAlias)
{
return _providers.Where(p => p.Alias == dataProviderAlias);
}
}
public class Provider
{
public string Type { get; set; }
public string Alias { get; set; }
}
Global.asax
For good design practice, you want to read data from web.config only once, and store them in static variables. Therefore, you want to initialize inside Application_BeginRequest of Global.asax.
public class Global : System.Web.HttpApplication
{
void Application_BeginRequest(object sender, EventArgs e)
{
DataProviders.Init();
}
}
Usage
var providers = DataProviders.GetData("FirstProvider").ToList();
Well, I'm not sure if I understand what you want to achieve, but to implement your idea you need a custom section handler.
http://msdn.microsoft.com/en-us/library/2tw134k3(v=vs.100).aspx
In case that you want to create a database connection for specific dataprovider, see this similar question:
ASP.NET: How to create a connection from a web.config ConnectionString?
In my case, I needed to store two byte[] variables in my Web.Config file. Since it must be valid XML data, I simply stored the contents of the arrays like so:
<appSettings>
<add key="Array1" value="0,1,2,3,4,5,6,7,8,9" />
<add key="Array2" value="0,1,2,3,4,5,6,7,8,9" />
</appSettings>
I then call a function that reads this into a C# string, split it into a string[], and parse each string element as a byte into a resulting byte[] and return it.

Get SQL Server CE path form multiple projects

To learn ServiceStack, I'm developing an API based in Northwind database (a SQL Server CE sdf file). My solution has 3 projects:
Northwind.Data. Database and POCO classes
Northwind.ServiceModel. DTO classes
Northwind.ServiceInstance. Service classes
What's the best way to access data? Currently the database is in Northwind.Data /App_Data folder. Can I access database path from Web.config and read it in AppHost class to create IDbConnection factory?
Thanks in advance.
What's the best way to access data?
I don't think OrmLite has support for SQL Server CE but there is this. Best way might be to just use SqlCeConnection within your Services.
Can I access database path from Web.config and read it in AppHost class to create IDbConnection factory?
You should be able to add the connection string to the Web.config file.
<add name="Test" connectionString="Data Source=C:\Northwind.sdf" />
If I'm correct about OrmLite not supporting SQL CE and you want IDbConnectionFactory like syntax in your Services you could look into using DBProviderFactories.
The simplest (not the best) thing I can think of would be doing something like below.
Create a 'bare bones' factory for SqlCEConnection. This assumes you have the connection string in your Web.config file
public class SqlCeFactory
{
public SqlCeConnection OpenConnection()
{
var conn = new SqlCeConnection(ConfigurationManager.ConnectionStrings["Test"].ToString());
try
{
conn.Open();
return conn;
}
catch (Exception ex)
{
throw ex;
}
}
}
Register it the SqlLCeFactory in your AppHost
public override void Configure(Funq.Container container)
{
container.Register<SqlCeFactory>(new SqlCeFactory());
}
Inject it into your Service(s)
public class SourceService : ServiceStack.ServiceInterface.Service
{
public SqlCeFactory DbFactory { get; set; }
public object Get(SomeRequest request)
{
using (var con = DbFactory.OpenConnection())
{
//use SqlCeConnection()
}
//more code
}
}

Entity Framework - using the same DbContext with different connection strings

I'm currently trying to use the same DbContext (I have two databases, of identical structure) in my application. I'm not quite sure what I'm doing wrong, but here's my current code - hopefully it should be pretty obvious what I'm trying to do. I'm using EF Database First (which the error at the bottom seems not to suggest).
My context factory code:
public class HOLContextFactory
{
public static HOLDbEntities Create()
{
return new HOLDbEntities(); // Works
}
public static HOLDbQuoteEntities CreateQuote()
{
return new HOLDbQuoteEntities(); // Gives error
}
}
public partial class HOLDbQuoteEntities : HOLDbEntities
{
public HOLDbQuoteEntities()
: base("HOLDbQuoteEntities") // This should send "HOLDbQuoteEntities" as the base connection string?!
// Also tried "name=HOLDbQuoteEntities"
{
}
}
Web.config connection strings:
<add name="HOLDbEntities" connectionString="metadata=res://*/HOLDbContext.csdl|res://*/HOLDbContext.ssdl|res://*/HOLDbContext.msl;provider=System.Data.SqlClient;provider connection string=<connstringdetails>" providerName="System.Data.EntityClient" />
<add name="HOLDbQuoteEntities" connectionString="metadata=res://*/HOLDbContext.csdl|res://*/HOLDbContext.ssdl|res://*/HOLDbContext.msl;provider=System.Data.SqlClient;provider connection string=<connstringdetails>" providerName="System.Data.EntityClient" /> // using diff database - same structure
Error I'm getting when using "HOLDbQuoteEntities" :
Code generated using the T4 templates for Database First and Model
First development may not work correctly if used in Code First mode.
To continue using Database First or Model First ensure that the Entity
Framework connection string is specified in the config file of
executing application. To use these classes, that were generated from
Database First or Model First, with Code First add any additional
configuration using attributes or the DbModelBuilder API and then
remove the code that throws this exception**
Entity Framework needs to use the actual entities object:
public class HOLContextFactory
{
public static HOLDbEntities Create()
{
// default connection string
return new HOLDbEntities();
}
public static HOLDbEntities CreateQuote()
{
// specified connection string
return new HOLDbEntities ("HOLDbQuoteEntities");
}
}
public partial class HOLDbEntities
{
public HOLDbEntities(string connectionString)
: base(connectionString)
{
}
}
}
I've done the same thing in one of my project. I am creating my entity context using metadata=res://*/
Try this:
<add name="HOLDbEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string=<connstringdetails>" providerName="System.Data.EntityClient" />
<add name="HOLDbQuoteEntities" connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string=<connstringdetails>" providerName="System.Data.EntityClient" />

Categories