Change Entity Framework provider in configuration - c#

I was hoping to be able to switch data providers to/from SQL Server and SQL Server Compact Edition via just a configuration change. But it doesnt work and looking at the EDMX file I think I can see why:
<edmx:StorageModels>
<Schema ... Provider="System.Data.SqlClient" ...
Is there any way to specify the provider in app.config or at runtime?

The Storage-Model is tied to a specific provider, which will cause the Entity Framework to reject any DbConnection implementations that are not compatible with the specified provider.
If you look at an Entity Framework connection-string, you can see that the StorageSchema, ModelSchema and Mapping are specified in three different files (which are generated from your .edmx and than embedded in the assembly). You could take your .edmx apart and embed the .ssdl, .csdl and .msl yourself and than create another .ssdl for SQL Server CE. This is basically just copy & paste and replacing the provider and some column-types.
I wrote about here: Comparison Entity Framework

For Unit Tests I change Schema this way (changing ssdl before main code execution).
In code:
var s = Assembly.GetExecutingAssembly().GetManifestResourceStream("Model1.ssdl");
var ssdlFilePath = "<some-dir>\file1.ssdl";
using (var file = File.Create(ssdlFilePath))
{
StreamUtil.Copy(s, file);
}
var str = File.ReadAllText(ssdlFilePath);
str = str.Replace("old provider token", "ProviderManifestToken=\"4.0\"");
str = str.Replace("old provider type"", "Provider=\"System.Data.SqlServerCe.4.0\"");
File.WriteAllText(ssdlFilePath, str);
In app.config:
<connectionStrings>
<add name="Database2Entities" connectionString="metadata=res://*/Model1.csdl|<some-dir>\file1.ssdl|res://*/Model1.msl;provider=System.Data.SqlServerCe.4.0;provider connection string="Data Source=|DataDirectory|\Database1.sdf"" providerName="System.Data.EntityClient" />
</connectionStrings>
It works)

Related

Entity Framework: The context is being used in Code First mode with code that was generated from an EDMX file

I am developing an WPF application with EF 6 database first approach, I am have 1 project in my solutions, if i run my project this error always appear.
The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
My mistake was using standard connection string in constructor
(Server = test\test; Database = DB; User Id = test_user;Password = test),
but Entity Framework needs different format
(metadata=res://*/DBModel.csdl|res://*/DBModel.ssdl|res://*/DBModel.msl;provider=System.Data.SqlClient;provider connection string="data source=test\test;initial catalog=DB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework""" providerName = ""System.Data.EntityClient)
Edit: Changed code to be formatted as code so it's easier to read.
EF makes assumptions based on the presence or absence of a metadata section in the connection string. If you receive this error you can add the metadata section to the connection string in your config file.
E.g. if your connection string looks like this:
<add name="MyModel" connectionString="data source=SERVER\INSTANCE;initial catalog=MyModel;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
Prepend metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl; so that it looks like this:
<add name="MyModel" connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;data source=SERVER\INSTANCE;initial catalog=MyModel;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
One thing you can do is... (if is Database first)
Open the .edmx[Diagram] -> right click -> "Update Model from database"
And see if the will appear the "Add", "Refresh" and "Delete" tabs.
If doesn't... probably your connection is broken and the dialog for VS creates a new connection string will appear instead. =)
You shouldnt use generated connection string, now you have all metadata files included in your solution. Instead try use in connection string section of app.config:
"data source=localhost\sqlexpress; initial catalog=sample; integrated security=True;MultipleActiveResultSets=True;"
None of the above solutions worked for me. But I did find the SqlConnectionBuilder class here which did work: https://learn.microsoft.com/en-us/dotnet/api/system.data.entityclient.entityconnectionstringbuilder?view=netframework-4.8
Its the same as specifying the string as some of the other suggestions here but it builds the string for you.
// Specify the provider name, server and database.
string providerName = "System.Data.SqlClient";
string serverName = ".";
string databaseName = "AdventureWorks";
// Initialize the connection string builder for the
// underlying provider.
SqlConnectionStringBuilder sqlBuilder =
new SqlConnectionStringBuilder();
// Set the properties for the data source.
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.IntegratedSecurity = true;
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder =
new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/AdventureWorksModel.csdl|
res://*/AdventureWorksModel.ssdl|
res://*/AdventureWorksModel.msl";
Console.WriteLine(entityBuilder.ToString());
using (EntityConnection conn =
new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
Console.WriteLine("Just testing the connection.");
conn.Close();
}
I also faced this exact same message, but workig with a web MVC project. This message is fired when I try to auto generate the Controller from the imported model. It seems that it is not working because "that was generated from an EDMX file".
The good news is that it works if I generate the model based in the "Code First" instead of "EF Designer". The bad news is that I can't use the EF Designer if I want that the automatically controller generation works. Does not matter which from those two ways you generates your model. Once the model is generated, you use it in the same way.
Tries to remove all your emdx objects from your project and recreate the model based in the Code First instead of EF Designer. Worked for me!
Very much late but still helpful. I got stuck in a similar problem. Posted a question about on SO and was able to find a solution. You can refer to Connection String errors in C# Web Api.
My situation was I had two connection strings in web.config (you'll get to know why when go to the link). Commenting one string was raising the error you got while commenting the other one was raising error as below:
An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor.
what i did was: I named my first connection string as DefaultConnection and in ApplicationDbContext class constructor I gave this DefaultConnection. Now my AccountController uses this connection string and all other controllers use second connection string.
This solved my problem.
I have two projects:
One is for the generated EDMX file and all related models.
The other one is the ASP.NET MVC Web.
I encountered this issue since the connection string that I am using on the ASP.NET MVC Web project is the normal string that I use using ADO.NET connection. So what I did is the following:
Open the app.config on your EDMX project files.
Copy its connection string.
Paste it on the WEB project since this will be used when you start
the application.

How to keep the "Provider Connection String" separate from the EF (EDMX) metadata information?

I would like to be able to handle the actual Connection String and the EF metadata connection string separately in the config (app.config, web.config) - the goal is to make the actual data-source more apparent.
I have complete control over creating the EF Context (yay IoC!), but don't want to hard-code any of the values. Preferably something like:
<add name="EfEntities"
connectionString="metadata=res://*/..;provider connection string=NO;.." />
<add name="EfEntities_Provider"
connectionString="data source=SERVER;initial catalog=DB;user id=ME" />
It would also be acceptable, and possibly better, is the deployed configs had only the conglomerated EF connection string - as long as it was built from separate properties in the source configs. (But this level of config transformation escapes me.)
I'm fine living with the conglomerated EF "connection string" for the Designer / Updater - the EDMX is in a separate project from the usage in the target assemblies that are deployed.
In my projects, I build the EF connection string myself in code and pass that to the Context object's constructor, like so:
void InitContext() {
String actualConnectionString = ConfigurationManager.ConnectionStrings["server123"].ConnectionString;
String efConnectionString = String.Format(CultureInfo.InvariantCulture, "metadata=res://*/..;provider connection string={0};.", actualConnectionString);
_context = new MyEFContext( efConnectionString );
}
I've decided to "go" with the idea behind Dai's answer. There may be problems with it (eg. the password better not contain a quote); but it works here on tests and feels more "visible" in config transformations.
The code looks about like:
var edmxMetadata = GetConnectionStringSetting("EfEntities_Metadata");
var providerConnection = GetConnectionStringSetting("EfEntities_Provider");
var edmxCS = string.Format(#"{0};provider={1};provider connection string=""{2}""",
edmxMetadata.ConnectionString,
providerConnection.ProviderName,
providerConnection.ConnectionString);
// (and by and by)
var context = new EfEntities(edmxCS);
Where:
<!-- just the metadata -->
<add name="EfEntities_Metadata"
connectionString="metadata=res://*/EfEntities.csdl|res://*/EfEntities.ssdl|res://*/EfEntities.msl"
providerName="System.Data.EntityClient" />
<!-- just the provider connection string -->
<add name="EfEntities_Provider"
connectionString="data source=SERVER;initial catalog=DB;user id=ME"
providerName="System.Data.SqlClient" />

Code First Entity Framework - change connection string

How do I change the connection string in a code first entity framework/MVC application? I'm trying to transfer it to a live site, but it overlooks web config values and still references my local version of the database.
Here is the connection string section of my web.config:
<add name="MembershipConnectionString" connectionString="Data Source=192.168.1.43;Initial Catalog=Website.Models.IntranetApplication;User Id=[UserName];Password=[Password];timeout=30" />
<add name="WebsiteConnectionString" connectionString="Data Source=192.168.1.43;Initial Catalog=Website.Models.IntranetApplication;User Id=[UserName];Password=[Password];timeout=30" />
<add name="Entities" connectionString="metadata=res://*/Models.IntranetModel.csdl|res://*/Models.IntranetModel.ssdl|res://*/Models.IntranetModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=192.168.1.43;Initial Catalog=Website.Models.IntranetApplication;User Id=[UserName];Password=[Password];MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
I'm not sure if the Entities string has any relevance, as I used Code First entity framework, and I think that only appeared when I tried to create an edmx file (although I ended up just deleting it). The Entities connection string has sat commented out so I don't think it's used.
I want entity framework to read the "WebsiteConnectionString", but it seems to want to use the local connection string, but I can't even see where that is set. How do I change it?
The connection string or its name can be passed to constructor of DbContext. If you are using default constructor it searches for the connection string with the same name as the name of your derived context class and if it doesn't find it, it uses this one:
Data Source=.\SQLEXPRESS; Integrated Security=True; MultipleActiveResultSets=True
With database name same like your context class.

Connecting to wrong database

Environment
.NET 3.5
Self Servicing
LLBL Pro 2.6
I know I might be doing something stupid here. I have following code
string connectionString = ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;
DbUtils.ActualConnectionString = connectionString;
PersonCollection ps = new PersonCollection();
ps.GetMulti(new PredicateExpression(Person.Lastname == "lastname" ));
Console.WriteLine(pt.Count);
Now when I generated the entities from LLBL Studio, I used a db named ForGeneratingLLBL but in app.config connection string is pointing to another db Master . My expection is that program will retrieve data from whatever is defined in DbUtils.ActualConnectionString (which in this case is defined in app.config) but for some reason its still retreiving data from ForGeneratingLLBL. Any idea what i am doing wrong here?
PS: I have posted this quetion on LLBL forum as well, trying here to see if anyone had similar issue before
If your DB is different than the one you generated the entities you need to put this in your config file:
<configuration>
<configSections>
<section name="sqlServerCatalogNameOverwrites" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
</configuration>
and this:
<sqlServerCatalogNameOverwrites>
<add key="OriginalDatabase" value="TargetDatabase" />
</sqlServerCatalogNameOverwrites>
In the documentation, under Catalog name overwriting

How to change the database - Schema used by Entity Framework (mysql database)?

I use EntityFramework in a project to connect to a Mysql database. The provider is Devart Dot.connect.
This application needs to connect to a database using connexion parameters given by the user at runtime. This includes of course the Mysql Database name.
I used the EntityConnectionStringBuiler and EntityConnection classes to build-up and store the custom connexion parameters.
The problem is that even with such given parameters, the application always connect to the database named when designing the EntityModel using the visual studio wizard.
What is very strange is that when debuging and checking the status of the ObjectContext, the custom connexion parameters are correctly used...
It makes me mad !!!!!
Any clue ?
After spending one day on this issue, I finally came to understand that the problem was coming from the model.edmx file.
In this file, you have one line per EntitySet.
On each EntitySet element there is an attribute called schema. In case of SQL Server this attribute is set to the related table schema :
EntitySet Name="annee_civile"
EntityType="openemisModel.Store.annee_civile"
store:Type="Tables" Schema="mydatabase" />
If you provide the name of the Schema when constructiong you own EntityConnection, it seem that there is a conflict and that finally, the Schema defined in the edmx file will be used even if you specified another one in the connection parameters.
The solution is simply to remove the name of the schema in the edmx file.
THIS WORKS FOR MYSQL, probably not when connecting to a SQL server.
EntitySet Name="annee_civile"
EntityType="openemisModel.Store.annee_civile"
store:Type="Tables" Schema="" />
The EntityConnectionStringBuilder :
string providedString = "User Id=xxxx;Password=xxx;Host=xxxx;Database=anydatabasename";
EntityConnectionStringBuilder entityConnBuilder = new EntityConnectionStringBuilder();
entityConnBuilder.Provider = "Devart.Data.MySql";
entityConnBuilder.Metadata = #"res:///OpenEmisModel.csdl|res:///OpenEmisModel.ssdl|res://*/OpenEmisModel.msl";
entityConnBuilder.ProviderConnectionString = providedString;
The EntityConnection and the object context using it:
EntityConnection entityConnexionEmis = new EntityConnection(entityConnBuilder.ConnectionString);
objectcontextEntities testingContext = new objectcontextEntities(entityConnexionEmis);
The software is now able to connect to any database name.
Hope this helps.
Reference the dll Devart.Data.MySql.Entity.EF6.dll in the project.
Somewhere when your application is starting up and before database operations take place, add the following:
var config = MySqlEntityProviderConfig.Instance;
config.Workarounds.IgnoreSchemaName = true;
You will need to reference:
using Devart.Data.MySql.Entity.Configuration;

Categories

Resources