I have developed a WinForm C# app that use ADO.NET Entity Framework for storing data.
I would like each user to have a database stored in their appdata\local folder but when I try to add the connection string to the users local app.config file I constantly get the error "ConfigurationSection properties cannot be edited when locked."
After I did some research I discovered the allowExeDefinition section setting.
I tried adding this setting for the connectionString section in the app.config file and at runtime (see code below) but I still get the same error whenever I try to save the configuration.
This is the code I use:
var connectionString = string.Format(ConnectionStringBase, dbLocation);
var exeConf = ConfigurationManager
.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);
var connectionStringSettings =
new ConnectionStringSettings(
"DatabaseEntities",
connectionString,
ProviderName);
exeConf.ConnectionStrings
.SectionInformation
.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser;
exeConf.ConnectionStrings.ConnectionStrings.Add(connectionStringSettings);
exeConf.Save(ConfigurationSaveMode.Minimal);
I have tried to search for a solution for this issue for days but I haven't been able to find anything usefull besides that I am considering storing the connection string in the users settings instead as a workaround but it feels kinda hackish.
Alright, instead of updating the app.config file I decided to create the connectionstring on runtime and pass it to the entity set constructor.
So when I initialize the entity set I use the following code instead:
var connectionString = string.Format(ConnectionStringBase, dbLocation);
var entities = new DatabaseEntities(connectionString);
The only thing to note is that if the connection string contains " you should replace these with single quotes ( ' ).
Related
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.
I am working on a Winforms application using Entity Framework 6 with an .EDMX diagram which generates the context and entities for me.
The connection string is stored in app.config by default.
I want to change the source of my connection string, and I want to retrieve it from the Windows registry.
How can I do that?
Try this:
MyEntities ctx = new MyEntities();
ctx.Database.Connection.ConnectionString = "...";
You can read connection string data from registry and assgin it to "ConnectionString" property.
It works but you have to assgin connection string everytime a new context object is created and also do not remove the original connection string from the app.config file.
I found a solution that must be for a older version then vs2010. I would like to know how to do this for vs2010? Does anyone know?
http://www.csharpbydesign.com/2008/01/overriding-dataset-settings-co.html
Let me explain little more detail.
I have a c# generated dataset. How can I change the connection string so I can use the dataset with another (identically structured yet differently populated) database? This has to occur at runtime as I do not know the server or database name at compile time. i AM USING vs2010 and SQL Server 2008 R2 Express
I think there is no simple way and you cannot change the Connection-String programmatically for the entire DataSet since it's set for every TableAdapter.
You need to use/create the partial class of the TableAdapter to change the connection-string since the Connection property is internal (if your DAL is in a different assembly). Don't change the designer.cs file since it will be recreated automatically after the next change on the designer. To create it just right-click the DataSet and chose "show code".
For example (assuming the TableAdapter is named ProductTableAdapter):
namespace WindowsFormsApplication1.DataSet1TableAdapters
{
public partial class ProductTableAdapter
{
public string ConnectionString {
get { return Connection.ConnectionString; }
set { Connection.ConnectionString = value; }
}
}
}
Now you can change it easily:
var productTableAdapter = new DataSet1TableAdapters.ProductTableAdapter();
productTableAdapter.ConnectionString = someOtherConnectionString;
Here's a screesnhot of my sample DataSet and the created file DataSet1.cs:
There's actually a much easier way to change the connection string.
Go to the Settings screen, where the connection string is displayed as a connection string.
First mark and copy the connection string that's displayed.
Then change the type from connection string to string. The text for the string will change to include xml.
Then paste the copied connection string over the xml text.
Then change the scope from Application to User.
When I want to change the connection string, I use the following code.
// assign the path to use to the variable fullpath (or whatever)
string newConnection = String.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}", fullpath);
Properties.Settings.Default.HootConnectionString = newConnection;
Properties.Settings.Default.Save();
In my case, I have a global Dataset active, so I have to make that the data is reread by the tableadapter. And, of course, you'll have to add error control to make sure the database is still there.
You'll notice that this will not change what is displayed in Application Settings. Those are defaults.
This works for an Access database; so your mileage and requirements may vary.
EDIT: Caveat. As it works out, when installed, the connection string works well for opening and reading database content, but it complains about not having a connection string when trying to update a database.
I am using the devart component dotconnect for postgresql. I have created the site using linq to entities, however, I would like each user to have a seperate database. This means that I need to change the connection string for each person that has logged in. I understand the main part of how to generate a new connection string etc, however, when i pass that as a paramater to the object context object it comes back with the error
"user id keyword not supported, "
if i create a class that generates an entity connection the error message changes to:
"Unable to load the specified metadata resource."
Cannot work out what I have done wrong in these instances.
ok so, as usual, when i posted this question, about 3 minutes later i found the problem. The entity connection string, for general purposes should have a cool little
res://*/
this makes the metadata work. This solves the problem of metadata resource and this works. So to help others who may, like me, have spent development time doing this, i created a class, with a method like so.
public static string getConnString(string database)
{
string connectionstring = "User Id=USER ID HERE;Password=PASSWORD HERE;Host=server;Database="+database+";Persist Security Info=True;Schema=public";
EntityConnectionStringBuilder newconnstring = new EntityConnectionStringBuilder();
newconnstring.Metadata = #"res://*/";
newconnstring.Provider = "Devart.Data.PostgreSql";
newconnstring.ProviderConnectionString = connectionstring;
return newconnstring.ToString();
}
then create a constructor like so
dataEntities data = new dataEntities(databaseConnection.getConnString(INSERTDBNAMEHERE);
Then we can reference that in the same way as a usual linq statement. Simples!!
I have two connection strings (both in Web.Config: CS_Local and CS_Production) for my DBML (Linq to SQL).
In my Global.Asax/Application_Start I run some production preparation methods if the request is non-local (!HttpContext.Current.Request.IsLocal). Within that part, I'd also like to change the current connection string used by my DBML from the standard CS_Local to CS_Production.
How would I do that? Some help please..
You can define the dbml context on the fly with:
string connectionString = HttpContext.Current.Request.IsLocal ?
ConfigurationManager.ConnectionStrings["CS_Local"].ConnectionString :
ConfigurationManager.ConnectionStrings["CS_Production"].ConnectionString;
yourDataContext = new YourApplicationDataContext(connectionString);