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())
{
}
Related
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.
my application is like one application with multiple database[all databse are with same schema] i need to switch the connection on dropdown select.i am now managing the all connection string with switch case but now i need to transfer the all connection string to class[.cs] file for globally use in hole app how to do this if session is correct then how to pass string using session to class file and how to retrieve it in hole project
now my cs file is:-
public class connectionstr { static string mulcon = "";
static SqlConnection myconnection = null;
public connectionstr()
{
// // TODO: Add constructor logic here //
}
public static SqlConnection getconnection(string opt)
{
if(opt=="RV001")
{
mulcon = ConfigurationManager.ConnectionStrings["DUM01ConnectionString"].ConnectionString;
}
else if(opt=="SV001")
{
mulcon = ConfigurationManager.ConnectionStrings["CompMasterConnectionString"].ConnectionString;
}
if(myconnection==null)
{
myconnection = new SqlConnection(mulcon);
myconnection.Open();
}
return myconnection;
}
}
but i need to add this in one webform which have dropdown the we shift the connection on dropdown selection and also which connection is selected that that connection is applied with all project webforms
What you essentially need is a single repository for the entire application. You have few options -
Singleton pattern - More details here - Basically you have to implement a singleton class which acts as a store for the connection string. Keep a dictionary in the singleton class. The key in the dictionary will be the user id, and the value will be the selected connectionstring. When the user selects the connectionstring, insert into the dictionary against the user. Wherever he needs a connection, use the connectionstring from the store.
You can do the same by storing the connectionstring in a session variable. As long the user session is valid, you can retrieve it and use it.
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.
Like the title. How can I do it?
I tried something, but it doesn't work like I was expecting.
I'm using an Entity Framework model. I need to pass my connection string like parameter, so, in another file, I've written
namespace MyNamespace.Model
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class MyEntities: DbContext
{
public MyEntities(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
}
}
When I startup the app, I call this constructor in this way, so I can refer to this from anyway in the app:
public static MyEntities dbContext = new MyEntities(mdlImpostazioni.SetConnectionString());
where mdlImpostazioni.SetConnectionString() returns a string (the data are correct):
server=192.168.1.100\SVILUPPO;database=MyDB;uid=myName;pwd=111111;
When I execute this code, it seems to be all ok, but when I try to make a query like:
var query = (from r in MainWindow.dbContext.TabTipoSistema select r);
it throws an exception from here:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException(); //exception here
}
So, this is a bad way... which is the right one? (using only code C#, not from xaml)
Your approach is correct, but you need to remember the connection string for EF requires the metadata and so on. So use the EntityConnectionStringBuilder. For example:
// the model name in the app.config connection string (any model name - Model1?)
private static string GetConnectionString(string model, YourSettings settings)
{
// Build the provider connection string with configurable settings
var providerSB = new SqlConnectionStringBuilder
{
// You can also pass the sql connection string as a parameter instead of settings
InitialCatalog = settings.InitialCatalog,
DataSource = settings.DataSource,
UserID = settings.User,
Password = settings.Password
};
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(#"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerSB.ConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = string.Format("res://*/Model.{0}.csdl|res://*/Model.{0}.ssdl|res://*/Model.{0}.msl", model); ;
return efConnection.ToString();
}
// Or just pass the connection string
private static string GetConnectionString(string model, string providerConnectionString)
{
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
// var efConnection = new EntityConnectionStringBuilder(#"metadata=res://*/model1.csdl|res://*/model1.ssdl|res://*/model1.msl;provider=System.Data.SqlClient;");
efConnection.Provider = "System.Data.SqlClient";
efConnection.ProviderConnectionString = providerConnectionString;
// based on whether you choose to supply the app.config connection string to the constructor
efConnection.Metadata = string.Format("res://*/Model.{0}.csdl|res://*/Model.{0}.ssdl|res://*/Model.{0}.msl", model);
// Make sure the "res://*/..." matches what's already in your config file.
return efConnection.ToString();
}
EDIT
The exception you get is because when you pass a pure SQL connection string, it assumes you are working with Code first, so it calls the OnModelCreation event. When you include the MetaData section as shown above, that tells EF it's a complete EF connection string.
I believe the problem lies on the Datasource you specify. You need to add the port of the connection, e.g if your SQL Server is configured on Port 1433, try:
server=192.168.1.100,1433\SVILUPPO;database=MyDB;uid=myName;pwd=111111;
more details about connection strings you can find Here
Also I am not sure if uid and pwd are valid, better try User ID and Password:
Server=192.168.1.100,1433\SVILUPPO;Database=MyDB;User ID=myName;Password=111111;
Finally mind the case sensitivity.
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);