support multiple database servers with Entity Framework - c#

I have an ASP.NET MVC2 application running with SqlServer. I need to support multiple databases (SqlServer, Mysql and Oracle). The schema is the same for all databases.
The edmx is configured to run with SqlServer, so I added two new ssdl files: one for MYSQL and one for Oracle.
With SQLSERVER I can run the application, but when I try to set the connection string and metadata at runtime to be configured with MYSQL it generates exception:
How would I go about altering the ssdl to achieve that?

I don't know how to do it specifically for MySql but this is what I've done to achieve multiple database support for Sql Server and Oracle. I believe the same approach works for MySql also. I expect you know how to set up Oracle client configuration. Changing the active connection string in application configuration file is all I need to do to target a different db.
1) Generate edmx against Sql Server.
2) Generate .ssdl and .msl files for Oracle. The latter contains entity property mappings. Data types need to be changed in ssdl for Oracle. See this link for detailed information. Oracle ssdl file needs to have the correct provider configuration, in my case: Provider="Oracle.ManagedDataAccess.Client".
3) Create new connection string for Oracle db connection in your application configuration file. It is crucial that namespaces are typed correctly here. Below is a working example:
<add name="MyConnectionString"
connectionString="metadata=res://*/CustomDb.csdl|res://CustomDbProject/CustomDbNamespace.CustomDb.ssdl|res://CustomDbProject/CustomDbNamespace.CustomDb.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string="DATA SOURCE=MYDS;USER ID=****;Password=****;Max Pool Size=**;Connection Timeout=120""
providerName="System.Data.EntityClient"/>
4) Create a default constructor for context:
public CustomDb()
: base("name=MyConnectionString")
{
Configuration.ProxyCreationEnabled = false;
}

Related

How can I specify a location to create database files for an Entity Framework Core application?

I have an application using Entity Framework Core to create an SQL Server database and its tables by applying migrations. I need to be able to specify the directory location where the database files will be created.
What I want to be able to do is either:
Have my application create the database with its files in the specified location before applying migrations
Have my application tell SQL Server where to create the database files, before applying migrations
I'm creating my DbContext using the connection string:
Data Source=ServerName;AttachDbFilename=specifiedPath\databasename.mdf;Initial Catalog=databasename;Integrated Security=True
I've tried having the application create the database using a standard SQL Create query before applying migrations. This causes the migrations to fail with the following exception:
Microsoft.Data.SqlClient.SqlException (0x80131904): Database 'databasename' already exists. Choose a different database name.
I assume this is because the DbContext or migrations are trying to create the database specified in the connection string.
Could I somehow edit the migration to remove the step where it creates the database? Or the DbContext?
Just in case anybody is looking to solve a similar problem:
I solved this by simply removing my code that checked if the database already existed. There's actually no need to manually create the file at all.
By specifying the file name in the connection string, using the
AttachDbFilename=specifiedPath\databasename.mdf
parameter, SQL server just created the file in that location.

Database first EF and ASP.NET Core 3 Web API published on Azure, connection string error

I'm developing an ASP.NET Core 3 Web API with a database first generated db context.
I have the connection string in the appsettings.json file.
Everything is fine when I run it locally on IIS Express.
The problem is that when I publish it on Azure, it gives me the error:
System.ArgumentException: Keyword not supported: 'data source'.
[...]
I noticed that the connection string, when published changed from:
metadata=res://*/DTOs.csdl|res://*/DTOs.ssdl|res://*/DTOs.msl;provider=System.Data.SqlClient;provider connection string='data source=*****;initial catalog=*****;persist security info=True;user id=*****;password=*****;MultipleActiveResultSets=True;App=EntityFramework'",
to:
metadata=res://*/DTOs.csdl|res://*/DTOs.ssdl|res://*/DTOs.msl;provider=System.Data.SqlClient;provider connection string="data source=*****;initial catalog=*****;persist security info=True;user id=*****;password=*****;MultipleActiveResultSets=True;App=EntityFramework""
As a work around I changed the line
services.AddScoped<palmdtos>(_ => new MyDbContext(Configuration.GetConnectionString("myConnectionString")));
to
services.AddScoped<palmdtos>(_ => new MyDbContext(Configuration.GetConnectionString("myConnectionString").Replace(""","'").Replace("&", "&")));
Is there a better way to do it?
Models created with the EF Designer are different from Code First in that your model already exists and is not generated from code when the application runs. The model typically exists as an EDMX file in your project.
The designer will add an EF connection string to your app.config or web.config file. This connection string is special in that it contains information about how to find the information in your EDMX file.
Refer to this article.
The cause was the connection string for one of the EDMX files we were using. Since the EDMX has to be read-only, we had to use a different connection string in Azure.
When replacing &quote; by a single quote ', it will work fine again. So go to azure website > Configuration > Connection strings > add your conn string with custom type.
Note: Make sure you also select Custom instead of SQLAzure for your Entity Framework connection string, even though the database runs on Azure.
Can you try updating the settings?
In Azure Panel:
Select App -> Application Settings -> Enter new Connection String -> Save

Entity Framework 5 : changing the database connection

I have a made an EntityFramework model based on my Demo Database.
I want to include connection strings for Staging and production and then in my Console App prompt the user to see which database they want to perform the operation on.
When I was prompted to setup the EF.edmx file I just chose to store the connection string in the app.config file. I have seen a link to change the Connection string of EntityFramework Context when initializing it here
However when I store another connection to my Staging Database, I get an error "Keyword not supported: 'metadata'"
So I stripped down the connection string not to include the EntityFramework type of parameters such as metadata=res://*/MyDBItems.csdl|res://*/MyDBItems.ssdl blah blah
and used a very simple database connection string
data source=myDB;initial catalog=myDB;user id=myUser;password=myPass;MultipleActiveResultSets=True;
now my Context does instanciate but when I get to a query I get another error about:
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.
How can I switch between different databases with Entity Framework 5, thanks!
forget it I got it....what I did...I made a 2nd constructor in the Context.cs file
public MyContext(string dbModel) : base("name="+dbModel) {
}
then in my app.config I have the various settings for the Demo,Staging & Production database connections....this took the full entityframework connection string. I think the link I provided was for Code-First but I am using Database First.

Azure Publish Database First Connection String Not Working

I have gone through the steps to publish my web app using database first on the azure portal.
However, when I publish I get this error message:
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.
My connection string in the web.config after it has been modified by publish:
<add name="MySiteEntities" connectionString="metadata=res://*/MySite.csdl|res://*/MySite.ssdl|res://*/MySite.msl;provider=System.Data.SqlClient;provider connection string="data source=tcp:**********.database.windows.net,****;initial catalog=MySite;user id=username#**********;password=*******;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
My context (generated by edmx):
public partial class MySiteEntities : DbContext
{
public MySiteEntities()
: base("name=MySiteEntities")
{
}
...
I am very confused becuase it seems like entity framework is trying to use code first rather than database first.
UPDATE:
I just tried using the same connection string locally and the web app seems to run fine. The web app does connect to the remote database fine. It is only when I publish to azure it fails.
Read my answer to a similar question at Entity framework work locally but not on azure.
If you made the same "mistake" I did, this is what's happening ... the Azure-deployed app isn't finding your connection string "MySiteEntities" inside your web.config. Instead, at the time your created your Azure Web Site (or Cloud Service or whatever), you created an associated Azure SQL Database and gave its connection string the exact same name, "MySiteEntities". This latter connection string is a "plain" connection string without Model/Database-first metadata references, and so is being treated as a Code-First connection by EF, which then complains about the conflict. See Code First vs. Database First for an explanation of this distinction.
It should be:
<connectionStrings>
<add name="MyDatabaseModelEntities"
connectionString="metadata=res://*/MyDBModel.csdl|res://*/MyDBModel.ssdl|res://*/MyDBModel.msl;
provider=System.Data.SqlClient;
provider connection string="
Data Source=<provideServerName>.database.windows.net;
Initial Catalog=MyDatabase;
Integrated Security=False;
User ID=<provideUserID>;
Password=providePassword>;
MultipleActiveResultSets=True;
Encrypt=True;
TrustServerCertificate=False""
providerName="System.Data.EntityClient"/>
</connectionStrings>
I changed connection string to remote (Azure) on my local web.config, then remove all set connection strings during publishing and publish web.config. It rewrites remove web.config. Then return connection string on local web.config to local connection. It works fine now.

Entity Framework 4.1 code first model compatibility issue after changing database from embedded to SQL Server Express

Hello Entity Frameworks Gurus!!
I've been following the official tutorial and have started a small project with it. I've started using SQL Server Compact Edition and have decided to change it to a SQL Server Express database.
After changing my connectionstring
<add name="SchoolContext" connectionString="Data Source=|DataDirectory|Registration.sdf" providerName="System.Data.SqlServerCe.4.0"/>
<!-- <add name="SchoolContext" connectionString="Data Source=.\SQLEXPRESS;Integrated Security=True;Initial Catalog=SchoolRegistration;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>-->
it started throwing this error:
Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention
has been added to the DbModelBuilder conventions.
What I don't comprehend is that I have an Initializer which implements the DropCreateDatabaseIfModelChanges
public class SchoolInitializer : DropCreateDatabaseIfModelChanges<SchoolContext>
and added the Initializer to the Global.asax.cs application_start()
Database.SetInitializer<SchoolContext>(new SchoolInitializer());
So after my error I deleted the SQL Server Compact .sdf file and switched back to its connection string and all the changes and all fixtures where put in it.
Why not SQL Server Express?
Something I am missing? Or should I have created another context for the new connection string and refactor my Initializer? Thanks for reading this
EF checks whether the model and the database are in sync by checking the values in the EdmMetadata table. In your case that table is missing in the database. But you are using the DropCreateDatabaseIfModelChanges initializer. Hence EF can not determine whether the model has been changed to execute the initializer.
If you want to use that initializer you need to let EF create the database with the EdmMetadata table (meaning dropping your express database so that EF can recreate it for you from your connectionString). Otherwise remove the initializer and manually do the changes to the database or use EF migrations.

Categories