I wish to pass a dynamic connection string to the entity framework context. I have over 150 schemas which are identical (one per account) and I would like to select the connection as such:
ApplicationDbContext db = new ApplicationDbContext("dbName");
In theory this would be fairly easy, as I can create a connectionString and pass it as the argument for the constructor, for example:
public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName)) { } public static string GetConnectionString(string dbName) { // The connectionString passed is something like: // Server=localhost;Database={0};Uid=username;Pwd=password var connString = ConfigurationManager .ConnectionStrings["MyDatabase"] .ConnectionString .ToString(); return String.Format(connString, dbName); }
I can connect successfully when I just pass the connection string name, but not when I generate it dynamically as below. I realize now that it's because the connection string in web.config has the providerName="MySql.Data.MySqlClient"
attribute in it.
When I pass the actual connection string dynamically to the connection though, it assumes that it needs to connect to SQL Server rather than MySQL and fails due to the connection string being invalid.
The question is, how do I pass the provider name to the connection string if I am creating it dynamically?
Log' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration.
MySQL Connector/NET integrates support for Entity Framework 6 (EF6), which now includes support for cross-platform application deployment with the EF 6.4 version.
If you want to change the connection string go to the app. config and remove all the connection strings. Now go to the edmx, right click on the designer surface, select Update model from database, choose the connection string from the dropdown, Click next, Add or Refresh (select what you want) and finish.
Entity Framework 6 offers some handy subtle changes which aid in both getting MySQL working and also creating dynamic database connections.
First, at the date of my answering this question, the only .Net connector drivers compatible with EF6 is the MySQL .Net Connectior 6.8.1 (Beta development version) which can be found at the official MySQL website here.
After installing, reference the following files from your Visual Studio solution:
You will also need to copy these files somewhere where they will be accessible to the project during build time, such as the bin directory.
Next, you need to add some items to your Web.config (or App.config if on desktop based) file.
A connection string:
<connectionStrings> <add name="mysqlCon" connectionString="Server=localhost;Database=dbName;Uid=username;Pwd=password" providerName="MySql.Data.MySqlClient" /> </connectionStrings>
Also add the provider, inside the <entityFramework />
and <providers />
nodes, optionally (this is an absolute must in the second part of my answer, when dealing with dynamically defined databases) you may change the <defaultConnectionFactory />
node:
<entityFramework> <defaultConnectionFactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6" /> <providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" /> </providers> </entityFramework>
If you change the defaultConnectionFactory from the default sql server connection, don't forget to remove the <parameter>
nodes which are nested in the defaultConnectionFactory node. The MysqlConnectionFactory does not take any parameters for its constructor and will fail if the parameters are still there.
At this stage, it's quite easy to connect to MySQL with Entity, you can just refer to the connectionString above by name. Note that if connecting by name, this will work even if the defaultConnectionFactory
node still points at SQL Server (which it does by default).
public class ApplicationDbContext: DbContext { public ApplicationDbContext() : base("mysqlCon") { } }
The it is just a matter of connecting normally:
ApplicationDbContext db = ApplicationDbContext();
At this point it's easy to connect to a database which we can pass as a parameter, but there's a few things we need to do.
If you have not already, you MUST change the defaultConnectionFactory in Web.config if you wish to connect to MySQL dynamically. Since we will be passing a connection string directly to the context constructor, it will not know which provider to use and will turn to its default connection factory unless specified in web.config. See above on how to do that.
You could pass a connection string manually to the context like this:
public ApplicationDbContext() : base("Server:localhost;...") { }
But to make it a little bit easier, we can make a small change to the connection string we made above when setting up mySQL. Just add a placeholder as shown below:
<add name="mysqlCon" connectionString="Server=localhost;Database={0};Uid=username;Pwd=password" providerName="MySql.Data.MySqlClient" />
Now we can build a helper method and change the ApplicationDbContext class as shown below:
public class ApplicationDbContext: DbContext { public ApplicationDbContext(string dbName) : base(GetConnectionString(dbName)) { } public static string GetConnectionString(string dbName) { // Server=localhost;Database={0};Uid=username;Pwd=password var connString = ConfigurationManager.ConnectionStrings["mysqlCon"].ConnectionString.ToString(); return String.Format(connString, dbName); } }
If you are using migrations, you will find that the ApplicationDbContext will be passed to your Seed method by the framework and it will fail because it will not be passing in the parameter we put in for the database name.
Add the following class to the bottom of your context class (or anywhere really) to solve that problem.
public class MigrationsContextFactory : IDbContextFactory<ApplicationDbContext> { public ApplicationDbContext Create() { return new ApplicationDbContext("developmentdb"); } }
Your code-first migrations and seed methods will now target the developmentdb
schema in your MySQL database.
Hope this helps someone :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With