EF Connection string without App.Config in startup project - c#

I'm trying to abstract EF in the DAL project of my solution. I've already reached the point that EF is only known in this project.
I've created a new Console.Test application which uses my BLL, which uses my DAL. Now this new console application requires an App.Config file which contains the EF connection string. My next step would be to get rid of this App.Config file aswell, since i would like to use my BLL on several platforms.
So i've created a partial class of my derived DbContext to add an extra constructor which accepts a full connection string. In my DAL i've also created a new static method for getting the connectionstring:
public static string GetSqlConnectionString(string serverName, string databaseName)
{
SqlConnectionStringBuilder providerCs = new SqlConnectionStringBuilder();
providerCs.DataSource = serverName;
providerCs.InitialCatalog = databaseName;
providerCs.IntegratedSecurity = true;
providerCs.UserID = "*****";
providerCs.Password = "******";
var csBuilder = new EntityConnectionStringBuilder();
csBuilder.Provider = "System.Data.SqlClient";
csBuilder.ProviderConnectionString = providerCs.ToString();
csBuilder.Metadata = "res://Prodomus.DAL/DataObjects.Entities.Model.csdl|res://Prodomus.DAL/DataObjects.Entities.Model.ssdl|res://Prodomus.DAL/DataObjects.Entities.Model.msl";
return csBuilder.ToString();
}
Now my problem is that i keep getting this error message stating: 'The underlying provider failed to open.'. I know for sure that the credentials i've used are correct, this also goes for the servername aswell as the databasename. Am i missing something here? Any help will be very much appreciated.
Thnx in advance!

You cannot mix Integrated security and username/password

Related

Entity Framework 6 connection string questions

I have a C# ASP.NET MVC code first project that works as intended to connect to my database. It has the connection string set in the web.config file and all seems to work great.
<connectionStrings>
<add name="HorstMFGContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|HorstMFG.mdf;Initial Catalog=aspnet-HorstMFG;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
Now I need to connect to the same database from a different application that needs to be a WinForms based class library. I don't have access to the source code of the program that uses my dll because my application is just a plug-in for Autodesk Vault.
There are numerous examples such as this one that show how to set the connection string in the application that calls the dll, but that obviously won't work in my case.
This link here seems to very close to what I need, but I haven't been able to get it to work. Here is my version of the 'Create' function.
public static HorstMFGEntities Create(string nameOrConnectionString)
{
var entityBuilder = new EntityConnectionStringBuilder();
// use your ADO.NET connection string
entityBuilder.ProviderConnectionString = nameOrConnectionString;
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/HorstMFG.ssdl|res://*/HorstMFG.msl";
return new HorstMFGEntities(entityBuilder.ConnectionString);
}
Here is the line that calls the function:
using (var db = HorstMFGEntities.Create(#"data source=(localdb)\MSSQLLocalDB;attachdbfilename=C:\Users\lorne\source\repos\HorstMFG\HorstMFG\App_Data\HorstMFG.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"))
{
foreach (string l in lineList3)
{
....
....
Here is the actual line that throws the exception.
// calculate material
Material mat = db.Materials.Where(m => m.StructuralCode == l.Split('\t')[6]).FirstOrDefault();
The exception message "Error: Keyword not supported: 'metadata'.
Any help to point me in the right direction is appreciated. Thanks.
I updated my code as per the first comment, and also added the 'provider' that I had missed as well.
public static HorstMFGEntities Create(string nameOrConnectionString)
{
var entityBuilder = new EntityConnectionStringBuilder();
// use your ADO.NET connection string
entityBuilder.ProviderConnectionString = nameOrConnectionString;
entityBuilder.Provider = "System.Data.SqlClient";
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/HorstMFG.csdl|res://*/HorstMFG.ssdl|res://*/HorstMFG.msl";
return new HorstMFGEntities(entityBuilder.ConnectionString);
}
Now I get the error "Error: Unable to load the specified resource."
I now followed the instructions in the link you provided. I think I must be getting close, but I'm a little foggy on the metadata format yet. There seems to be a portion commented out in the example. I replaced it with this:
entityBuilder.Metadata = "res://*/HorstMFG.csdl|res://*/HorstMFG.ssdl|res://*/HorstMFG.msl";
Now I get the error: "Unable to load the specified metadata resource"
I confirmed that the files I am referencing do exist, they are in the ...\obj\Debug\edmxResourcesToEmbed\ folder in my project. I also changed the 'build action' for the 'HorstMFG.edmx' object from 'None' to 'Embedded Resource'. That didn't help anything.

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.

Add a connection string to local user config file throws lock exception

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 ( ' ).

How to use a SQL connection string with ADO.NET Entity Data Model

I am trying to use the ADO.NET Entity Data Model in a way that I can on the fly change which database I point too. Changing databases may require an entirely new connection string. Some databases are on different servers. So I need the ability to pass my ADO.NET Entity Data Model a custom connection string formated like so 'server=severaddress;database=database1;User ID=test;Password=test1234;'
Edited: My Entity Class implements ObjectContext. The three constructers I can use is the default, pass in connectionString, pass in an EntityConnection. When ever I use the overload constructers I get errors saying it doesn't recognize "server" in the connectionstring.
I need to either instantiate my repository with a custom connection string, or be able to set it before use.
ObjectContext accepts entity connection string in its constructor. Entity connection string consists of three parts:
Metadata location (location of mapping XMLs produced by EDMX file)
Data storage provider
Data store connection string (that is what you want to provide)
You have several ways to achieve what you want. Generally what you need is combine two parts of connection string:
string format = "metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=\"{0}\"";
string connectionString = "server=severaddress;database=database1;UserID=test;Password=test1234;"
var context = ModelContext(String.Format(format, connectionString));
The format describes location of metadata from Model.edmx included as resources in assembly and Sql provider. Second part is your connection string.
Be aware that this will only work if all your databases have same schema and use same provider.
I have done this before, just pass the connection string in one of the overloaded constructor of the auto generated DbContext derived class.
Entity contexts have constructors that take the connection string as an argument. I believe you can either provide the string itself, or the name of a string from your connectionStrings element in your config files.
So the trick is to avoid creating your contexts by just saying new EntityContext(). One simple way to do this is to use a factory.
public class ContextFactory : IContextFactory
{
public EntityContext Get()
{
var connectionString = ... // Do some logic to get the connection string
return new EntityContext(connectionString);
}
}
...
using (var context = new ContextFactory().Get())
{
...
}
The ideal way to use this is in connection with dependency injection, so that you're not even tightly coupled with the new ContextFactory() implementation:
public class MyRepository : IMyRepository
{
private readonly IContextFactory _contextFactory;
public MyRepository(IContextFactory contextFactory)
{
_contextFactory = contextFactory;
}
public GetObjects()
{
using(var context = _contextFactory.Get())
{
}
}
}
This gives you ultimate flexibility when it comes to deciding how your contexts will be instantiated.
Try this:
In web.confige, create a copy of your existing connection string and give it a different name. Change the connection string attributes for this new connection string. e.g.
If you previously had a connection string declared as
<add name="MyEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="data source=MySQL1;initial catalog=MyDB;user id=sa;password=password123;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Add another one giving it a new name
<add name="MyEntities2" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string="data source=MySQL2;initial catalog=MyDB;user id=sa;password=password987;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Then in your code files, add the "using System.Data.EntityClient;" Namespace. Declare an entityConnection object and assign the default server.
EntityConnection econn = new EntityConnection("name=MyEntities");
YOu can access the default DB using the following code
using (var _context = new MyEntities(econn))
{ .......}
Later in code you can switch between the servers using the following code:
econn = new EntityConnection("name=MyEntities2");
YOu can access the second DB using the following code
using (var _context = new MyEntities(econn)) <== This will point to second server now.
For passing connectionstring to ObjectContext derived class, I found a solution from the following link:
http://blogs.msdn.com/b/rickandy/archive/2008/12/09/explicit-connection-string-for-ef.aspx

linq to entities changing database connection string in code

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!!

Categories

Resources