Change Entity Framework Connecting String To Server - c#

Here is what i have so far :
<add name="gymEntities1" connectionString="metadata=res://*/DateModel.csdl|res://*/DateModel.ssdl|res://*/DateModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=gym;user id=sa;password=xxxx;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
it works on my LocalHost Database, and I can load my Data from it.
however, I have a server, installed sqlserver with my database on that, basicaly when i change my sqlcommands connecting string this work but in some part of my program I used entity framework and have no idea how to change it connecting string, with some posts in stackoverflow I change that to
<add name="gymEntities2" connectionString="metadata=res://*/DataModel.csdl|res://*/DataModel.ssdl|res://*/DataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=tcp:46.105.124.144;initial catalog = gym ;User ID=sa;Password=xxxx"" providerName="System.Data.EntityClient" />
but it still read datas from my localhost and not connect to my server.
I don't know how when i change this connecting string to my server it still read data from my localhost database.
what is the best way to change connecting string from App.Config?

First Possible Issue:
It is less likely since other people suggested to you.But, it is possible that you are missing a connection string in one of your web.config or app.config.
It is a good habit to copy your string to every project. Example. I have 3 different projects in my solution (Library, WCF, WPF). I copied the following connection string to each project (One sample for Local SQL Server and another for Azure):
<connectionStrings>
<add name="LocalSQLServerSample.CodeREDEntities" connectionString="metadata=res://*/CodeRED.csdl|res://*/CodeRED.ssdl|res://*/CodeRED.msl;provider=System.Data.SqlClient;provider connection string="data source=MachineName\ServerName;initial catalog=CodeRED;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="AzureSQLServerSample.CodeREDEntities" connectionString="metadata=res://*/CodeRED.csdl|res://*/CodeRED.ssdl|res://*/CodeRED.msl;provider=System.Data.SqlClient;provider connection string='data source=azureservername.database.windows.net;initial catalog="CodeRED";persist security info=True;user id=CodeRED;password=R%Chd$g*VHs28eEr;MultipleActiveResultSets=True;App=EntityFramework'" providerName="System.Data.EntityClient" />
</connectionStrings>
Second possible issue:
You have mentioned that you are using entity framework. Are you using ObjectContext to access it? If yes, I have the method below to call it every time I want to access any database:
From sample above: name="LocalSQLServerSample.CodeREDEntities"
_containerName is CodeREDEntities (The same for all my connections).
environment is to determine which database you are connecting to. For example, in the above connection sample, I have LocalSQLServerSample and AzureSQLServerSample and I usually have something like PRODUCTION, DEVELOPMENT, TESTING....
public static ObjectContext getObjectContext(string environment, bool isReadOnly)
{
environment = environment == null ? "" : environment.Trim();
environment = environment.Length == 0 ? "" : (environment + ".");
ObjectContext objectContext = new ObjectContext(
ConfigurationManager.ConnectionStrings[environment + _containerName].ToString());
objectContext.DefaultContainerName = _containerName;
objectContext.CommandTimeout = 0;
objectContext.ContextOptions.ProxyCreationEnabled = !isReadOnly;
return objectContext;
}
Sample of how to use it:
Common is a common class that I use to store shared information such as getting common error format used for Common.getInnerExceptionMessage.
Also, you don't have to always pass environment, you can store it as a constant to be able to call it such as (I always pass it to be able to mix connection when I need to for specific calls): You can modify connection from anywhere by changing _selectedEnvironment if you do not wish to pass it everywhere.
public const string _ENVIRONMENT_DEVELOPMENT = "LocalSQLServerSample";
public const string _ENVIRONMENT_PRODUCTION = "AzureSQLServerSample";
public static string _selectedEnvironment = _ENVIRONMENT_PRODUCTION;
Sample of getting item based on id:
Note: User is a class generated by entity framework from database.
public UsersDataGrid GetItem(string environment, long id)
{
ObjectContext objectContext = Common.getObjectContext(environment, false);
try
{
var item = objectContext.CreateObjectSet<User>()
.Where(W => W.ID == id)
.Select(S => new UsersDataGrid()
{
Active = S.Active,
ID = S.ID,
Unique_ID = S.Unique_ID,
First_Name = S.First_Name.ToUpper(),
Last_Name = S.Last_Name.ToUpper(),
Email = S.Email,
School = S.School.Title.ToUpper(),
Gender = S.Gender.Title.ToUpper(),
TShirt_Size = S.TShirt_Size.Title.ToUpper(),
GUID = S.GUID + "",
Note = S.Note,
Machine_User = S.Machine_User,
Machine_Name = S.Machine_Name,
Created_On = S.Created_On,
Last_Updated_On = S.Updated_On
}).FirstOrDefault();
return item;
}
catch (Exception exception)
{
return new UsersDataGrid()
{
Note = ("Service Error: " +
Common.getInnerExceptionMessage(exception))
};
}
}
2nd Sample: Updating a user:
Note: Common.CopyValuesFromSourceToDestinationForUpdate is only a generalized method copying items from item object to entityItem, instead you can copy values normally such as entityItem.ID = item.ID and so on...
public Result Update(string environment, User item)
{
ObjectContext objectContext = WCF_Service_Library.Classes.Common.getObjectContext(environment, false);
try
{
var entityItem = objectContext.CreateObjectSet<User>()
.AsEnumerable().Where(Item => Item.ID == item.ID).ToList().FirstOrDefault();
if (entityItem == null)
return new Result("Item does NOT exist in the database!");
entityItem = Common.CopyValuesFromSourceToDestinationForUpdate(item, entityItem) as User;
objectContext.SaveChanges();
return new Result(entityItem.ID);
}
catch (Exception exception)
{
return new Result("Service Error: " + Common.getInnerExceptionMessage(exception));
}
}
Third issue (it does not look like it, but you may encounter it):
If you publish your app and ONLY sign your WPF project, you will not get error during publishing, but you may not be able to connect to the database. You must sign all your projects in your solution.
Hopefully this help you with your problem

Check the WebConfig of your startup project. Entity framework reads ConnnectionString from AppConfig when you run Update Model From Db operation .
But in runtime it reads ConnnectionString from WebConfig in your Startup project

I hope it is use for you
Add this for App.Config files
<connectionStrings>
<add name="Dbconnection"
connectionString="Server=localhost; Database=OnlineShopping;
Integrated Security=True"; providerName="System.Data.SqlClient" />
</connectionStrings>

This connection string must be work:
<add name="Name"
connectionString="metadata=<Conceptual Model>|<Store Model>|<Mapping Model>;
provider=<Underlying Connection Provider>;
provider connection string="<Underlying ConnectionString>""
providerName="System.Data.EntityClient"/>
If you have any problems with writing connection string, you can use following code on the page.

Related

When Entity Framework Connection Gets Open & Closed

I have an asp.net web forms application it uses EF for all database activities. When page loads I have to fetch lot of data from different tables. I have a DataAccessor class where I am having a member variable of Entity Framework DbContext (MyDBEntities). See class definition below.
public class DataAccessor
{
public static DataAccessor Instance = new DataAccessor();
private MyDBEntities dbEntities = new MyDBEntities();
private DataAccessor()
{
}
public FetchTable_1_Data()
{
return dbEntities.Table1.Where( x => x.Id = something).List();
}
public FetchTable_2_Data()
{
return dbEntities.Table2.Where( x => x.Id = something).List();
}
public FetchTable_n_Data()
{
return dbEntities.TableN.Where( x => x.Id = something).List();
}
}
Using data accessor as below in page load
Page_Load()
{
Repeater1.DataSource = DataAccessor.Instance.FetchTable_1_Data();
Repeater1.DataBind();
Repeater2.DataSource = DataAccessor.Instance.FetchTable_2_Data();
Repeater2.DataBind();
}
My Questions are,
When DB connection is getting open in my case
When DB connection getting closed?
Do I need to use using(MyDBEntities dbEntities = new MyDBEntities()) instead of using member variable
If i would need to use as question #3, do I need to open connection using "using" statement in each fetch methods?
My database connection is broken sometimes and system performance is getting degrade, i suspect my usage of EF. Can someone advice me how to use EF?
Some more questions,
How connection pooling is working with EF?
connectionString="metadata=res:///ReviewsDb.csdl|res:///ReviewsDb.ssdl|res://*/MyDb.msl;provider=System.Data.SqlClient;provider connection string="data source=SERVER;initial catalog=MyDB;persist security info=True;user id=sa;password=mypwd;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient" />
I am using above connection string, do I have connection pool with above connection string?
How can I configure connection in EF
Appreciate any help on these questions.
thank you friends
You dataaccessor is a static member.
Stay away from using static since it may survive between page accesses. It is not hard to imagine what damage that could cause.
I have got database errors from the previous page access when I was doing that. I had to scratch my head a lot.
Also use == when comparing instead of =.
You donĀ“t have to use using.
I would actually advise you to have a data accessor that your Page_Load will create with something like var accessor = new DataAccesssor(); instead of using your approach with a private constructor.
Now it will be clear for you which lifetime your MyDbEntities instance will have. It will be scoped to your Page_Load function.

How to use a dynamic connection string using a Model First approach but still use the data model in the EDMX?

I have created an EDMX using EF 5 with the Model First approach, i.e. I started with a blank designer and modeled my entities. Now I want to be able to use this model defined in the EDMX but supply runtime SQL Server connection strings without modyfing the config file.
I know how to pass a connection string to the DbContext but the issue is locating the metadata for the mappings within the assembly.
For example, my EDMX has this connection string in the app.config
<add name="MesSystemEntities" connectionString="metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;provider=System.Data.SqlClient;provider connection string="data source=MyMachine;initial catalog=MesSystem;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
The part that I am missing is the "metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;"
I want to be able to create a DbContext programmatically passing in a SQL Server connection string but "add on" the metadata portion.
This is what I would like to be generated by the T4 file...
public partial class MesSystemEntities : DbContext
{
public MesSystemEntities()
: base("name=MesSystemEntities")
{
}
public MesSystemEntities(string sqlServerConnectionString)
: base(GetEfConnectionString(sqlServerConnectionString))
{
}
private string GetEfConnectionString(string sqlServerConnectionString)
{
// values added by T4 generation
string format = "metadata=res://*/Data.DataContext.EntityFramework.MesSystem.csdl|res://*/Data.DataContext.EntityFramework.MesSystem.ssdl|res://*/Data.DataContext.EntityFramework.MesSystem.msl;;provider=System.Data.SqlClient;provider connection string=\"{0}\"";
return String.Format(format, sqlServerConnectionString);
}
...
}
My question is how can I get the metadata I need in the T4 generation file to create the Entity Framework connection without hardcoding it for each EDMX file
OR
is there an easier way to load the metadata from the assembly programmatically?
I had the same issue, so instead of relying on all the meta data in the connection string (which I think is not a good idea) I wrote a method to create it from a standard connection string. (I should probably refactor it into an Extension method for DbContext, but this should do)
internal static class ContextConnectionStringBuilder
{
// Modified Version of http://stackoverflow.com/a/2294308/209259
public static string GetEntityConnectionString(string ConnectionString,
Type ContextType)
{
string result = string.Empty;
string prefix = ContextType.Namespace
.Replace(ContextType.Assembly.GetName().Name, "");
if (prefix.Length > 0
&& prefix.StartsWith("."))
{
prefix = prefix.Substring(1, prefix.Length - 1);
}
if (prefix.Length > 1
&& !prefix.EndsWith("."))
{
prefix += ".";
}
EntityConnectionStringBuilder csBuilder =
new EntityConnectionStringBuilder();
csBuilder.Provider = "System.Data.SqlClient";
csBuilder.ProviderConnectionString = ConnectionString.ToString();
csBuilder.Metadata = string.Format("res://{0}/{1}.csdl|"
+ "res://{0}/{1}.ssdl|"
+ "res://{0}/{1}.msl"
, ContextType.Assembly.FullName
, prefix + ContextType.Name);
result = csBuilder.ToString();
return result;
}
}
Basic usage is something like:
string connString =
ConfigurationMananager.ConnectionStrings["name"].ConnectionString;
string dbConnectionString = ContextConnectionStringBuilder(connString,
typeof(MyDbContext));
var dbContext = new MyDbContext(dbConnectionString);

How to in-code supply the password to a connection string in an ADO.Net Entity Data Model

I've been following this tutorial on how to create an OData service.
http://www.hanselman.com/blog/CreatingAnODataAPIForStackOverflowIncludingXMLAndJSONIn30Minutes.aspx
And it works flawlessly ... but, in the Entity Data Model Wizard, when it asks you to "Choose Your Data Connection" it gives you this warning.
"This connection string appears to contain sensitive data (for example, a password) that is required to connect to the database. Storing sensitive data in the connection string can be a security risk. Do you want to include this sensitive data in the connection string?"
If I choose: "No, exclude sensitive data from the connection string. I will set it in my application code."
I do not see where I can, "in my application code" insert the password. (My company stores them encrypted in the registry)
Plus, I have multiple DBs that I need to connect to, depending on the environment (Dev, CA, or Prod) and I need to know what DB is referenced in the connection string to get the correct password.
Thanks.
When you create your context, you can set a connection string. To build this connection string, you can parse the connection string without the password with an EntityConnectionStringBuilder and then parse the inner connection string with an other ConnectionStringBuilder, depending on your browser. Then you can set the password and pass it to the constructor.
var originalConnectionString = ConfigurationManager.ConnectionStrings["your_connection_string"].ConnectionString;
var entityBuilder = new EntityConnectionStringBuilder(originalConnectionString);
var factory = DbProviderFactories.GetFactory(entityBuilder.Provider);
var providerBuilder = factory.CreateConnectionStringBuilder();
providerBuilder.ConnectionString = entityBuilder.ProviderConnectionString;
providerBuilder.Add("Password", "Password123");
entityBuilder.ProviderConnectionString = providerBuilder.ToString();
using (var context = new YourContext(entityBuilder.ToString()))
{
// TODO
}
I added a "dummy" password in the configuration file ("XXXXX"), then replaced that value with the real password in the entity constructor
public MyDatabaseContainer() : base("name=MyDatabaseContainer")
{
Database.Connection.ConnectionString = Database.Connection.ConnectionString.Replace("XXXXX","realpwd");
}
Modify the constructor of the entities
public sampleDBEntities() : base("name=sampleDBEntities")
{
this.Database.Connection.ConnectionString = #"Data Source=.\;Initial Catalog=sampleDB;Persist Security Info=True;User ID=sa;Password=Password123"; ;
}
My sample application was written in "Database First" mode and the "CreateNewConnectionString" method below works just fine (though it doesn't look all that elegant.)
The "CreateNewConnectionString2" method looks really elegant, BUT causes an exception telling me it's only valid in "Code First" mode.
So I'm providing both methods along with the constructor I modified to use my methods. NOTE AND BEWARE, I've modified code generated by a template and that is subject to being overwritten if the code is regenerated. To me it seems like the right place to put it.
If your application was generated in "Code First" mode, you may need to use "CreateNewConnectionString2" (I have not yet tested this option.)
I hasten to admit that I copied both code blocs from other postings as I don't yet know nearly enough about all this to write my own code.
private static string CreateNewConnectionString(string connectionName, string password)
{
var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~").ConnectionStrings.ConnectionStrings[connectionName];
//or:
//var config = ConfigurationManager.ConnectionStrings[connectionName];
var split = config.ConnectionString.Split(Convert.ToChar(";"));
var sb = new System.Text.StringBuilder();
for (var i = 0; i <= (split.Length - 1); i++)
{
if (split[i].ToLower().Contains("user id"))
{
split[i] += ";Password=" + password;
}
if (i < (split.Length - 1))
{
sb.AppendFormat("{0};", split[i]);
}
else
{
sb.Append(split[i]);
}
}
return sb.ToString();
}
private static string CreateNewConnectionString2(string connectionName, string password)
{
var originalConnectionString = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
var entityBuilder = new EntityConnectionStringBuilder(originalConnectionString);
var factory = DbProviderFactories.GetFactory(entityBuilder.Provider);
var providerBuilder = factory.CreateConnectionStringBuilder();
providerBuilder.ConnectionString = entityBuilder.ProviderConnectionString;
providerBuilder.Add("Password", password);
entityBuilder.ProviderConnectionString = providerBuilder.ToString();
return entityBuilder.ProviderConnectionString;
}
public ChineseStudyEntities()
: base(CreateNewConnectionString("ChineseStudyEntities", "put YOUR password here")) // base("name=ChineseStudyEntities")
{
}

Set the database name when using oData and EF

I have a scenario where there are multiple dbs that have the same schema and clients can pick which database to query. Is there a way to include the database name when doing an oData query from silverlight so it can reuse the same services?
Lets say I have this query (see below) being executed at the client (silverlight/wp7), how do I get this query to run against the database that the user picked when they first launched the app?
private DataServiceCollection _employees;
private void LoadEmployees()
{
DataModelContainer dmc = new DataModelContainer(new Uri("http://localhost:63832/DataService.svc"));
var query = (from e in dmc.Employees
where e.StartDate == BaseDate
select e);
_employees = new DataServiceCollection(dmc);
_employees.LoadCompleted += new EventHandler(_employees_LoadCompleted);
_employees.LoadAsync(query);
}
You should be doing that in your configuration files, via connectionstrings element.
eg:
<configuration>
<!-- Other configuration settings -->
<connectionStrings>
<add name="Sales"
providerName="System.Data.SqlClient"
connectionString= "server=myserver;database=Products;uid=<user name>;pwd=<secure password>" />
<add name="NorthWind"
providerName="System.Data.SqlClient"
connectionString="server=.;database=NorthWind;Integrated Security=SSPI" />
</connectionStrings>
To retrieve the connection strings dynamically, based on your query string from the client, make use of the ConfigurationManager class. The following links will help you in this regard:
http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx
www.dotnet-guide.com/configurationmanager-class.html
Here is what I came up with: The AddQueryOption will add a value to the query string, in my case the key of the db that I want to run the query against.
var query = (from e in dmc.Employees.AddQueryOption("dbKey", SelectedDB)
where e.StartDate == BaseDate select e);
_employees = new DataServiceCollection(dmc);
_employees.LoadCompleted += new EventHandler(_employees_LoadCompleted);
_employees.LoadAsync(query);
}
In the DataService class I overrride the CreateDataSource method and return a DataModelContainer with the correct connection string for the query
protected override DataModelContainer CreateDataSource()
{
DataModelContainer dmc = new DataModelContainer(GetConnectionString());
return dmc;
}
private string GetConnectionString()
{
string dbKey = HttpContext.Current.Request.Params["dbKey"].ToString();
string cnnKey = "DataModelContainer" + dbKey;
return ConfigurationManager.ConnectionStrings[cnnKey].ToString();
}

LINQ to SQL connectionstring

I have an application that I want to be able to configure the connection string for my LINQ to SQL. I've tried so many different ways but cannot seem to get it working. I want to do this dynamically in the code when the app is run, the reason for this is that the user can change the connection settings.
If I delete the connectionString out of app.config the application still works OK (communicating) which makes me wonder where I should be changing the connection string?
I think that the best way to do it is a combination of Albin's and Rup's answers. Have a value in the config file, and then read it at run time and feed it to the context constructor, something like this:
WEB.CONFIG:
<appSettings>
<add key="ConString" Value="The connection string" />
CODE:
//read value from config
var DBConnString = System.Configuration.ConfigurationManager.AppSettings("ConString");
//open connection
var dataContext= new MyDataContext(sDBConnString)
this way you can change the connection string even at runtime and it will work and change on the running program.
You can pass an override connection string into the DataContext constructor:
var db = new MyDataContext("Data Source=Something Else;")
The DBML class (YourDataContext) has an overloaded constructor which takes ConnectionString, so try instantiating that instead of the default one.Get the connection string from app.config and use that to create the instance.
YourDataContext context = new YourDataContext (ConfigurationManager.ConnectionStrings["ConnStringInAppConfig"].ConnectionString)
You should change it in app.config. The reason it works without is that the LINQ2SQL designer creates a fallback to the connection string used when designing the DBML. If you define a connection string in app.config that is used instead.
By Default your constructor look like this
public dbDataContext() :
base(global::invdb.Properties.Settings.Default.Enventory_4_0ConnectionString, mappingSource)
{
OnCreated();
}
You can change return value Instead of
//Original
public string Enventory_4_0ConnectionString {
get {
return ((string)(this["Enventory_4_0ConnectionString"]));
}
}
this
//Modified code
public string Enventory_4_0ConnectionString {
get {
return (System.Configuration.ConfigurationManager.ConnectionStrings["Enventory_4_0ConnectionString"].ConnectionString);
}
}
Inside your dbml file designer.cs add this dynamic call to base class constructor. It will work for local, dev and prod automatically pulling from current web.config without need to pass connection every time;
public HallLockerDataContext() :
base(ConfigurationManager.ConnectionStrings["MYDB1"].ConnectionString, mappingSource)
{
OnCreated();
}
Usage:
using (var db = new HallLockerDataContext())
{
}

Categories

Resources