I have winforms app with SQL Db on my localServer. I added EF5 using Database_First.
The question is:
How to change the connection string of EF5 Model in "Runtime" using "OpenFileDialog"?
I want to provide the app with a "Feature" to let the client specify his Database Server where the app db is located.
There are two problems that need to be considered.
First DbContext has constructor that takes a user defined connection string, but this constructor is not exposed in the generated code for your context, so you have to add it in a partial file outside of the generated code.
And then the Entity Framework connection string itself differs from a typical SqlClient connection string, so you have to use EntityConnectionStringBuilder to build an appropriate connection string.
For example consider this sample code:
public partial class MyContext: DbContext
{
public MyContext(string efConnectionString):base(efConnectionString)
{
}
public static MyContext CreateContextFromAdoCS(string adoConnectionString)
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = "System.Data.SqlClient";
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = adoConnectionString;
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/MyModel.csdl|
res://*/MyModel.ssdl|
res://*/MyModel.msl";
var efCs = entityBuilder.ToString();
return new MyContext(efCs);
}
}
If you have an existing SqlClient connection string you can use the factory method to create an instance of your context.
Here Display a ConnectionString dialog you can see how to open a standard dialog to construct an SqlClient connection string.
Let it be in App.config
<add name="ConnectionStringNew" connectionString="Data Source=ServerName;user id=sa;Password=sasa;initial catalog=[DataBase]" />
Have a Combobox where you want to let the user to select the DataBase.
FIll the combobox with below coding.
SqlConnection con1 = new SqlConnection (ConfigurationManager.ConnectionStrings["ConnectionStringNew"].ConnectionString);
SqlCommand comm = new SqlCommand("SELECT ROW_NUMBER() OVER(ORDER BY NAME) AS ID,NAME FROM SYS.SYSDATABASES WHERE DBID > 4 ORDER BY NAME", con);
SqlDataAdapter da = new SqlDataAdapter(comm);
da.Fill(dtblDataBase);
cmbDataBase.DataSource = dtblDataBase;
cmbDataBase.ValueMember = "ID";
cmbDataBase.DisplayMember = "NAME";
Replace the DataBase Name Like below.
DataBaseName = Convert.ToString(con1.ConnectionString);
CommonVariables.strDataBaseName = DataBaseName.Replace("[DataBase]", cmbDataBase.Text.Trim());
CommonVariables.strCompanyName = cmbDataBase.Text.Trim();
I have just given a coding sample.. Customize it as you want.
Related
I have a project that uses entity framework data model(.edmx) in it's data layer.I want to add work station id in connection string to store it during create log in database.
This is what I do:
var d = new PresentModelConnectionString();
string connectionString = d.Database.Connection.ConnectionString;
string lastCharacter = connectionString.Substring(connectionString.Length - 1, 1);
if (lastCharacter == ";")
{
connectionString += $"workstation id={Helpers.UserId.ToString()}";
}
else
{
connectionString += $";workstation id={Helpers.UserId.ToString()}";
}
d.Database.Connection.ConnectionString = connectionString;
return d;
But when it tries to connect to database and get data returns The login for user sa failed.When I remove this line:
d.Database.Connection.ConnectionString = connectionString;
It works fine.
This is the connection string:
<add name="PresentModelConnectionString" connectionString="metadata=res://*/PresentModel.csdl|res://*/PresentModel.ssdl|res://*/PresentModel.msl;provider=System.Data.SqlClient;provider connection string="data source=192.168.1.101\sql2014;initial catalog=MIS;user id=sa;password=sa_123;connect timeout=600000000;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
How can I include work station id dynamically to connection string?
Thanks
After searching several hours I found this solution, it change the connection string of entity framework database first model.As Alex recommended in comments I should use SqlConnectionStringBuilder to make connection string.
Create a partial class for model context in a separate file for adding constructor that gives connection string as parameter:
public partial class PresentModelConnectionString
{
public PresentModelConnectionString(string connectionString):base(connectionString)
{
}
}
Make connection string:
//connection string in web.config
//Data Source=192.168.1.101\sql2014;Initial Catalog=MIS_Keshavarzi_980906;user id=sa;pwd=sa_123; Connect Timeout=60000;
string connectionString =
System.Configuration.ConfigurationManager.AppSettings["ABSConnectionString"];
SqlConnectionStringBuilder connectionStringBuilder = new
SqlConnectionStringBuilder(connectionString);
connectionStringBuilder.WorkstationID = Helpers.UserId.ToString(); //get work station id
connectionStringBuilder.ApplicationName = "EntityFramework"; //set application name
For modifying the model connection string use EntityConnectionStringBuilder:
EntityConnectionStringBuilder entityConnectionBuilder = new
EntityConnectionStringBuilder();
entityConnectionBuilder.Metadata =
"res://*/PresentModel.csdl|res://*/PresentModel.ssdl|res://*/PresentModel.msl";
entityConnectionBuilder.Provider = "System.Data.SqlClient";
entityConnectionBuilder.ProviderConnectionString =
connectionStringBuilder.ConnectionString;
PresentModel should change with your model name.
Finally create a new instance of model context with this connection string:
var entityContext = new
PresentModelConnectionString(entityConnectionBuilder.ConnectionString);
I have a server that hosts 50 databases with identical schemas, and I want to start using Entity Framework in our next version.
I don't need a new connection for each of those databases. The privileges of the one connection can talk to all of the 50 databases, and for data management and speed (this is a WebAPI application) I don't want to instantiate a new EF context every time I talk to each of the databases if I don't have to, unless of course if this occurs each time a request comes to the server then no big deal.
All I really need is the ability to change the USE [databasename] command, which I assume eventually gets sent to the server from EF.
Is there a way to accomplish this in code? Does EF maintain a read/write property in the Context that refers to the database name that could be changed on the fly before calling SaveChanges(), etc.??
Thank you!!!
bob
Don't Work hard, work smart !!!!
MYContext localhostContext = new MYContext();
MYContext LiveContext = new MYContext();
//If your databases in different servers
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("localhost", "Live");
//If your databases have different Names
LiveContext.Database.Connection.ConnectionString = LiveContext.Database.Connection.ConnectionString.Replace("DBName-Localhost", "DBName-Live");
the structure for databases should be the same ;)
You can take a look at:
SO question about passing existing SQL Connection to
EntityFramework Context
and at this article describing how to
change database on existing connection.
Please let me know if any additional help is needed.
Edited
Updated 2nd link to point to SqlConnection.ChangeDatabase method.
So eventually code would look similarly to the following:
MetadataWorkspace workspace = new MetadataWorkspace(
new string[] { "res://*/" },
new Assembly[] { Assembly.GetExecutingAssembly() });
using (SqlConnection sqlConnection = new SqlConnection(connectionString))
using (EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection))
using (NorthwindEntities context = new NorthwindEntities(entityConnection))
{
// do whatever on default database
foreach (var product in context.Products)
{
Console.WriteLine(product.ProductName);
}
// switch database
sqlConnection.ChangeDatabase("Northwind");
Console.WriteLine("Database: {0}", connection.Database);
}
It is very simple
I had
public WMSEntities() : base("name=WMSEntities") //WMSEntities is conection string name in web.config also the name of EntityFramework
{
}
already in autogenerated Model.Context.cs of edmx folder.
To connect to multiple database in runtime, I created another constructor that takes connection string as parameter like below in same file Model.Context.cs
public WMSEntities(string connStringName)
: base("name=" + connStringName)
{
}
Now, I added other connection string in Web.Config for example
<add name="WMSEntities31" connectionString="data source=TESTDBSERVER_NAME;initial catalog=TESTDB;userid=TestUser;password=TestUserPW/>
<add name="WMSEntities" connectionString="data source=TESTDBSERVER_NAME12;initial catalog=TESTDB12;userid=TestUser12;password=TestUserPW12/>
Then, when connecting to database I call below method passing connectionString name as parameter
public static List<v_POVendor> GetPOVendorList(string connectionStringName)
{
using (WMSEntities db = new WMSEntities(connectionStringName))
{
vendorList = db.v_POVendor.ToList();
}
}
Here's my solution for just changing the database name. Simply pull the string from the web or app.config file, modify it, and then instantiate:
string yourConnection = ConfigurationManager.ConnectionStrings["MyEntities"].ConnectionString.Replace("MyDatabase", yourDatabaseName);
dcon = new MyEntities(yourConnection);
I have implemented this in my current project in which we have a common security database and different database for every client in the project. So our security database has a table that contain connection string for every other database. We just pass client id and get the connection string of the client database..
For this add two EDMX one for the common database and other for common schema databases. When user login or what might be your scenario to choose database go to common databse and get the connection string and create object of the needed database. Here is Code sample any, if any quer let me know..
You can keep connection string regarding every other database in a table in a a common database shared by all the other database.
EntityInstance_ReviewEntities.GetContext(GetConnectionString(ClientId));
private string GetConnectionString(int TenantId)
{
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
ISecurityRepository objSecurity = new SecurityRepository();
string tenantConnectionString = objSecurity.GetClientConnectionString(TenantId);
entityBuilder.ProviderConnectionString = tenantConnectionString;
entityBuilder.Provider = "System.Data.SqlClient";
entityBuilder.Metadata = #"res://*/ClientEntity.YourEntity.csdl|res://*/ClientEntity.ADBClientEntity.ssdl|res://*/ClientEntity.YourEntity.msl";
return entityBuilder.ToString();
}
EntityConnection.ChangeDatabase method is not supported, but SqlConnection.ChangeDatabase works fine.
So you have to use SqlConnection in entity framework database's constructor:
using MvcMyDefaultDatabase.Models;
using System.Data.Metadata.Edm;
using System.Data.SqlClient;
using System.Data.EntityClient;
using System.Configuration;
using System.Reflection;
public ActionResult List(string Schema)
{
SqlConnection sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString);
MetadataWorkspace workspace = new MetadataWorkspace(new string[] { "res://*/" }, new Assembly[] { Assembly.GetExecutingAssembly() });
EntityConnection entityConnection = new EntityConnection(workspace, sqlConnection);
sqlConnection.Open();
sqlConnection.ChangeDatabase(Schema);
Models.MyEntities db = new MyEntities(entityConnection);
List<MyTableRecords> MyTableRecordsList = db.MyTableRecords.ToList();
return View(MyTableRecordsList);
}
With this code you can read the tables with the same format (same table name and same fields) of several schema passing the database name in the "Schema" string.
For SQL Server, if you want to change only the database, not a connection, try:
public class XXXXDbContext : DbContext
{
public string databaseName
{
set
{
Database.GetDbConnection().Open();
Database.GetDbConnection().ChangeDatabase(value);
}
}
}
In my web site I have regular ADO.NET connection string like:
,
now Entity Framework added it's own connection string to same database.
How is it possible to use only one ADO.NET connection string and build Entity Connection string in runtime?
you can use EntityConnectionStringBuilder to generate connection string at runtime dynamically at runtime but you still need metada for this
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";
using (EntityConnection conn =
new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
Console.WriteLine("Just testing the connection.");
conn.Close();
}
I'm trying to use Entity Framework and it put it's connection string into app.config. I would like to move it to code as it's easier for me at this stage of development.
metadata=res://*/database.csdl|res://*/database.ssdl|res://*/database.msl;provider=System.Data.SqlClient;provider connection string="data source=computer;initial catalog=database;persist security info=True;user id=user;password=Mabm#A;multipleactiveresultsets=True;App=EntityFramework"
How can I make Entity Framework use connection string from code rather then look at the app.config? Alternatively if it's not possible how can I pass parameters to app.config (like dbname, dbuser, dbpassword)?
You can use EntityConnectionStringBuilder for this purpose.
Check here
public string GetConnectionString()
{
string connectionString = new EntityConnectionStringBuilder
{
Metadata = "res://*/Data.System.csdl|res://*/Data.System.ssdl|res://*/Data.System.msl",
Provider = "System.Data.SqlClient",
ProviderConnectionString = new SqlConnectionStringBuilder
{
InitialCatalog = ConfigurationManager.AppSettings["SystemDBName"],
DataSource = ConfigurationManager.AppSettings["SystemDBServerName"],
IntegratedSecurity = false,
UserID = ConfigurationManager.AppSettings["SystemDBUsername"],
Password = ConfigurationManager.AppSettings["SystemDBPassword"],
MultipleActiveResultSets = true,
}.ConnectionString
}.ConnectionString;
return connectionString;
}
When you create an instance of your ObjectContext derived class, you can simply pass the connection string as a constructor argument.
Rather than use a username and password, why not use Integrated Security? It is more secure and easier to manage.
i.e. 'Trusted_Connection = Yes' in your connection string and securely manage access through AD.
Connection Strings
First, create your context using the constructor with the connectionString parameter.
http://msdn.microsoft.com/en-us/library/gg679467(v=vs.103).aspx
Note that it's not directly this constructor that you must call, but the specific inherited context constructor for your database that your Entity generator created for you.
Furthermore, if you want to pass the username and password at runtime, you can create a connection string using this class:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnectionstringbuilder.aspx
See here:
http://msdn.microsoft.com/en-us/library/bb738533.aspx
If the connection string log in details are always the same then I would suggest that you use ConfigurationManager to retrieve the connection string from your app.config and encrypt the ConnectionStrings section of the file.
If I'm letting Visual Studio take care of adding an SQL Server database to an existing project, it adds the connection string to app.config. How can I use use THAT connection string to make my own connections and datasets?
Use the ConfigurationManager.AppSettings to read the connection string when required.
For example, if you opening a SQL Connection, use the assign the "Connection String" property to the value retrieved from ConfigurationManager.AppSettings ("MyConnectionString")
If it is placed in the appropriate section in the app config file, then you can use ConfigurationManager.ConnectionStrings to retrieve it as well.
Read more here http://msdn.microsoft.com/en-us/library/ms254494.aspx
Place the connection string in your app.config then use
ConfigurationManager.ConnectionStrings[str].ConnectionString.ToString();
to get the connection string.
For example:
private string GetConnectionString(string str)
{
//variable to hold our return value
string conn = string.Empty;
//check if a value was provided
if (!string.IsNullOrEmpty(str))
{
//name provided so search for that connection
conn = ConfigurationManager.ConnectionStrings[str].ConnectionString.ToString();
}
else
//name not provided, get the 'default' connection
{
conn = ConfigurationManager.ConnectionStrings[ConnStr].ConnectionString;
}
//return the value
return conn;
}
Then you can reference the connection using ado.net or Linq
For Example:
your app.config would contain an entry like:
<connectionStrings>
<add name="nameofConnString" connectionString="Data Source=SQLDATA;Initial Catalog="nameofdatabase";Persist Security Info=True;User ID=username;Password=password;Connection Timeout=30;Pooling=True; Max Pool Size=200" providerName="System.Data.SqlClient"/>
'
Then you could call
conStr = GetConnectionString("nameofConnString")
With Ado.net
You could then establish the connection with:
sqlConn = new SqlConnection(conStr);
sqlConn.Open();
Or with Linq
LinqData ld = new LinqData();
DataContext dataContext = new DataContext(ld.GetConnectionString(sqlConn));
where LinqData is a class that contains the GetConnectionString() method.
Well, both of those helped get me on the right track. I found this quite simple, yet highly annoying. The solution I used was:
using System.Configuration;
add a reference System.configuration
create a new connection with SqlConnection(ConfigurationManager.ConnectionStrings["MyDatabaseConnectionFromApp.Config"].ConnectionString)