So I guess this is really simple, but for some reason I'm unable to find the answer. My problem is that I've before used EF 4.3.1 contexts that inherit from ObjectContext, and the autogeneration always created an overloaded constructor that accepted the connection string as a parameter.
Now that I'm trying to switch to EF 5.0, I have to use the DbContext version. But MyEntities that is inherited from DbContext, has only the parameterless constructor available. I guess I could add the overloaded constructor myself, and make it call base(connectionString), but doing manual changes to the auto-generated file just seems like a risky business at best.
So how can I create an instance of MyEntities that uses a connection string that I provide at runtime?
Have you tried using the connectionFactory?
This example is for SqLite, but it applies to all databases.
You can make a class similar to this one:
public class SqLiteConnectionFactory : IDbConnectionFactory
{
public System.Data.Common.DbConnection CreateConnection(string nameOrConnectionString)
{
var databaseDirectory = #"C:\\master.db";
var builder = new SQLiteConnectionStringBuilder
{
DataSource = databaseDirectory,
Version = 3
};
return new SQLiteConnection(builder.ToString());
}
}
and then use if by executing this statement before you access your context the first time:
Database.DefaultConnectionFactory = new ConnectionFactories.SqLiteConnectionFactory ();
Here is a function to build your connection string (for firebird here):
private static string ConnectionString(string dbFileName)
{
// Specify the provider name, server and database.
const string providerName = "FirebirdSql.Data.FirebirdClient";
const string metaData = "res://*/RcModel.csdl|res://*/RcModel.ssdl|res://*/RcModel.msl";
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
FbConnectionStringBuilder sqlBuilder = new FbConnectionStringBuilder();
sqlBuilder.UserID = "sysdba";
sqlBuilder.Password = "masterkey";
sqlBuilder.DataSource = #"127.0.0.1";
sqlBuilder.Database = dbFileName;
sqlBuilder.Dialect = 3;
sqlBuilder.Charset = "UTF8";
sqlBuilder.ServerType = FbServerType.Default;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = sqlBuilder.ConnectionString;
entityBuilder.Metadata = metaData;
return entityBuilder.ToString();
}
Use it that way:
string cs = ConnectionString(#"C:\myDbFile.fbd");
EntityConnection conn = new EntityConnection(cs);
MyEntities db = new MyEntities(conn);
You can do it where you create MyEntities. Something like this:
MyEntities dataContext = new MyEntities();
dataContext.Database.Connection.ConnectionString = "<YOUR CONNECTION STRING>";
If your edmx is setup to look for a connection string in your config it will still do so when created but you can strip out the database provider connection string that embedded inside it. After doing that it would look something like this (if connecting to SQL):
<connectionStrings>
<add name="MyEntities" connectionString="metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=System.Data.SqlClient;provider connection string=;" providerName="System.Data.EntityClient" />
</connectionStrings>
Related
I have an app that the connection string changes by per user and machine. that said I have made a test connection string just to get it testing. Then once that is working I will add the dynamic connection string.
After some research I have figured out that there is a problem with the connection string.
If someone could please tell me where I am wrong I would appreciate it.
var s = #"metadata=res://*/ProcurementModel.csdl|res://*/ProcurementModel.ssdl|
res://*/ProcurementModel.msl;provider=System.Data.SqlClient;
provider connection string=&';data source=JAMES-DESKTOP\SQLEXPRESS;initial catalog=MyDatabase;persist security info=True;user id=User;password=*****;MultipleActiveResultSets=True;App=EntityFramework&';";
Update:
public ProcurementContext()
{
var s =
#"metadata=res://*/ProcurementModel.csdl|res://*/ProcurementModel.ssdl|
res://*/ProcurementModel.msl;provider=System.Data.SqlClient;
provider connection string=&';data source=JAMES-DESKTOP\SQLEXPRESS;initial catalog=MyDatabase;persist security info=True;user id=jd;password=P#ssw0rd;MultipleActiveResultSets=True;App=EntityFramework&';";
_connectionString = s;
}
Getting data:
public List<Procurement> ParcelListByUser(string userName)
{
using (var context = new ProcurementEntities(_connectionString))
{
return context.Procurements.Where(p => p.UserName == userName).ToList();
}
}
Constructor:
public ProcurementEntities(string connectionString)
: base(connectionString)
{
}
Error message:
Format of the initialization string does not conform to specification
starting at index 165.
Configuration:
The configuration of the Procurement
public class ProcurementConfiguration:DbConfiguration
{
public ProcurementConfiguration()
{
SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
SetDefaultConnectionFactory(new SqlConnectionFactory(ConnectionStrings.LocalConnectionString));
}
}
I think the issue is in your connection string. I've made the same thing and I have a function to create the connection string in an automatic way.
The code:
public static string GetConnectionString()
{
// Build the provider connection string with configurable settings
string cn = "server=" + mdlImpostazioni.p.dbServer;
cn += ";database=" + mdlImpostazioni.p.dbName;
cn += ";uid=" + mdlImpostazioni.p.dbUser;
cn += ";pwd=" + mdlImpostazioni.p.dbPassword + ";";
var providerSB = new SqlConnectionStringBuilder(cn);
var efConnection = new EntityConnectionStringBuilder();
// or the config file based connection without provider connection string
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 = #"res://*"; //-----> very important
return efConnection.ToString();
}
In this way, I pass the return value to my db context constructor, like in your code. My constructor is:
public partial class Entities : DbContext
{
public Entities(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
public void Close()
{
this.Dispose();
}
}
Try it and ask if you have some problem.
One way to change your connection string dynamically is to only change entity framework underlying connection's connection string. Something like this:
myDbContext.Database.Connection.ConnectionString = "Data source=JAMES-DESKTOP\SQLEXPRESS;initial catalog=MyDatabase;persist security info=True;user id=DynamicUser;password=DynamicPassword;MultipleActiveResultSets=True;App=EntityFrameworkForUser";
This way, your application does not have to hardcode tokens related to entity framework (i.e. metadata).
I need to set my Entity Framework connection string at runtime. Right now, I have the following:
string connectionString = "metadata=res://*/DataModels.CustomerDataModel.csdl|res://*/DataModels.CustomerDataModel.ssdl|res://*/DataModels.CustomerDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=tcp:{serverName},{portNumber};initial catalog={databaseName};user id={username};multipleactiveresultsets=True;application name=EntityFramework"";
using (CustomerEntities entities = new CustomerEntities(connectionString))
{
CustomerEntity entity = new CustomerEntity();
// do more
entities.CustomerEntities.Add(entity);
entities.SaveChanges();
}
When I execute the code above (with the {parameter} values replaced), I get the following error:
Keyword not supported: 'data source'.
What am I doing wrong?
Change this.
string connectionString = "metadata=res://*/DataModels.CustomerDataModel.csdl|res://*/DataModels.CustomerDataModel.ssdl|res://*/DataModels.CustomerDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=tcp:{serverName},{portNumber};initial catalog={databaseName};user id={username};multipleactiveresultsets=True;application name=EntityFramework"";
To this (note how i escaped the " character as "" )
string connectionString = #"metadata=res://*/DataModels.CustomerDataModel.csdl|res://*/DataModels.CustomerDataModel.ssdl|res://*/DataModels.CustomerDataModel.msl;provider=System.Data.SqlClient;provider connection string= ""data source=tcp:{serverName},{portNumber};initial catalog={databaseName};user id={username};multipleactiveresultsets=True;application name=EntityFramework""";
I know this was asked 10 months ago, but I found an easier way to specify the connectionString:
If your config file has it as:
<connectionStrings>
<add name="CustomerDataModel" connectionString="metadata=res://*/EntityFramework.CustomerDataModel.csdl|res://*/EntityFramework.CustomerDataModel.ssdl|res://*/EntityFramework.CustomerDataModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.\CustomerDataModel;initial catalog=CustomerDB;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
You can specify it as -
public const string ConnectionString = #"name=CustomerDataModel";
..
CustomerDBContext context = new CustomerDBContext(ConnectionString );
No need to worry about quotes. Lot cleaner.
It is easier to use EntityConnectionStringBuilder and SqlConnectionStringBuilder to change parameters as you want.
set multiple connection strings in your web.config, and follow below:
public partial class MyDatabaseEntities
{
public MyDatabaseEntities(string connection)
: base(connection)
{
}
}
and then wherever you want to create instance of entities, pass connection string name in parameter:
MyDatabaseEntities entities = new MyDatabaseEntities("CONNECTION_STRING_NAME");
I hope this will help.
Thanks
I want to create a custom config screen so that I can modify the LINQ database connection at runtime. Apart from changing the app.config which would then require me to restart the software, is there anyway I can change the LINQ database connection string at runtime? And store this in the Project's Settings?
This is the code I use in my project. It's static so can be called anywhere. Change MyEntities and MyModel for the appropriate names for your project.
public static MyEntities NewContext()
{
var y = new System.Data.EntityClient.EntityConnectionStringBuilder();
y.Provider = "System.Data.SqlClient";
string conn = CodeToGetConnectionStringHere();
if(!conn.EndsWith(";")) conn += ";";
conn += "MultipleActiveResultSets=true";
y.ProviderConnectionString = conn;
y.Metadata = "res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl";
return new MyEntities(y.ConnectionString);
}
You can safely store your connection string in project settings; and build it using EntityConnectionStringBuilder class.
class ConnectionStringFactory
{
internal stati string BuildModelConnectionString(string connectionString)
{
var builder = new EntityConnectionStringBuilder
{
Provider = "System.Data.SqlClient",
Metadata = #"your metadata string",
ProviderConnectionString = connectionString
};
return builder.ConnectionString;
}
}
You can then use the method from above in your code like this:
var connectionString = ConnectionStringFactory.BuildModelConnectionString(Settings.ConnectionString);
using(var dataContext = new DataContext(connectionString))
{
// your logic here...
}
I'd like to supply the connection string for my database at runtime. I am using the Entity Framework. This is what I have so far
class MyClassDBContext:DbContext
{
public MyClassDBContext(string str) : base(str)
{
this.Database.Connection.ConnectionString = str;
}
}
To use the above code, I tried
//create connection string
EntityConnectionStringBuilder myConn = new EntityConnectionStringBuilder();
myConn.Provider = "System.Data.SqlClient";
myConn.ProviderConnectionString = "user id=xxxx;password=xxxx;server=localhost;database=xxxx;connection timeout=30";
//inject the connection string at runtime
MyClassDBContext a = new MyClassDBContext(myConn.ToString())
The above code gave me an error saying "Provider keyword not supported".
To attempt to debug this error, I tried the following
MyClassDBContext a = new MyClassDBContext("metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=user id=xxxx;password=xxxx;server=localhost;database=xxxx;connection timeout=30")
Now, I got an error saying "metadata keyword not supported". So I changed my code to
MyClassDBContext a = new MyClassDBContext("provider=System.Data.SqlClient;provider connection string=user id=xxxx;password=xxxx;server=localhost;database=xxxx;connection timeout=30")
Now I got an error saying "provider keyword not supported". So I again changed my code to
MyClassDBContext a = new MyClassDBContext("user id=xxxx;password=xxxx;server=localhost;database=xxxx;connection timeout=30")
and now it works!. My question is : how do I specify the provider and metadata at runtime? It looks like only the connection string is being accepted. I am using Entity 4.3.1 from Nuget.
Thanks
edmx file based EF require the "Provider" and "Metadata" content. Code-first based EF doesn't require this, requiring only the regular connection string. You could use a SqlConnectionStringBuilder (instead of EntityConnectionStringBuilder) to build this normal connection string if you'd like. But as you've seen, you need only specify the actual connection details. The Provider and Metadata aren't needed in EF 4.3.1's DbContext Code-first paradigm.
Building on HatSoft's answer:
var entityConnectionStringBuilder= new EntityConnectionStringBuilder();
entityConnectionStringBuilder.Provider = "System.Data.SqlClient";
entityConnectionStringBuilder.ProviderConnectionString = <your SQL Server connection string>;
entityConnectionStringBuilder.Metadata = "res://*";
MyClassDBContext a = new MyClassDBContext(entityConnectionStringBuilder.ToString());
The EntityConnectionStringBuilder class can be used to to specify provider and metadata at runtime
e.g.
var entityConnectionStringBuilder= new
EntityConnectionStringBuilder();
entityConnectionStringBuilder.Provider = "System.Data.SqlClient";
entityConnectionStringBuilder.Metadata =
"res:///Example.csdl|res:///Example.ssdl|res://*/Example.msl";
Please see for more on CSDL, SSDL & MSDL in Metadata
I followed this link
and also this one
How to use EF Code-First without an app.conf file?
Basically what I do is almost like you, create a constructor with a string and calling the base.
But I also set the provider in this constructor.
here's a example
public Context(string ConnectionString) : base(ConnectionString) {
Database.DefaultConnectionFactory = new SqlCeConnectionFactory("Oracle.DataAccess.Client");
}
That way you can specify the provider. And you won't get the provider keyword error since you don't need to specify in the connection string
Here's how I call it.
var dbCont = new ClassLibrary1.Models.Context("DATA SOURCE=xxx;PASSWORD=xxx;USER ID=xxx");
Hope that helps took me long time to find it
It's old question but maybe it will be useful for someone
var provider = (DbProviderFactory)System.Data.Entity.DbConfiguration
.DependencyResolver
.GetService(typeof(DbProviderFactory), "invariant provider name");
var conn = provider.CreateConnection();
//conn.ConnectionString = "sample connection string";
DbInterception.Dispatch.Connection.SetConnectionString(conn, new DbConnectionPropertyInterceptionContext<string>()
.WithValue("sample connection string"));
return new SampleDbContext(conn,true);
In .Net is there a class in .Net where you can get the DB name, and all the connection string info without acutally doing a substring on the connection string?
EDIT:
I am not creating a connection I am attempting to get info out of the connection string. So I am basicly looking for something that takes a connection string arg and has accessors to dbName, connection type, etc....
You can use the provider-specific ConnectionStringBuilder class (within the appropriate namespace), or System.Data.Common.DbConnectionStringBuilder to abstract the connection string object if you need to. You'd need to know the provider-specific keywords used to designate the information you're looking for, but for a SQL Server example you could do either of these two things:
Given
string connectionString = "Data Source = .\\SQLEXPRESS;Database=Northwind;Integrated Security=True;";
You could do...
System.Data.Common.DbConnectionStringBuilder builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = connectionString;
string server = builder["Data Source"] as string;
string database = builder["Database"] as string;
Or
System.Data.SqlClient.SqlConnectionStringBuilder builder = new System.Data.SqlClient.SqlConnectionStringBuilder();
builder.ConnectionString = connectionString;
string server = builder.DataSource;
string database = builder.InitialCatalog;
After you initialize the connection with the connection string, you can get those information from properties of the initialized connection object.
Check System.Data.Common.DbConnection.
ConnectionInfo connectionInfo = new ConnectionInfo ();
connectionInfo = logOnInfo.ConnectionInfo;
connectionInfo.DatabaseName = database;
connectionInfo.ServerName = server;
connectionInfo.Password = password;
connectionInfo.UserID = user;
EDIT: Looks like Nathan beat me to it, as mine is from the same page.
EDIT AGAIN: I should note that ConnectionInfo is in the CrystalDecisions.Shared namespace. As for how to get it from a generic DB connection, I'm not sure.
Yep ConnectionInfo
http://msdn.microsoft.com/en-us/library/ms226340(VS.80).aspx
EDIT: I, along with Chris, realized that this is only works if you have the Crystal Reports namespaces imported. Otherwise I'm not sure
if you build your connection string using the Connection string builder (e.g. OracleConnectionStringBuilde, and it will be different for different database), in that case easily retrieve the information out of it.
here it explained:
http://msdn.microsoft.com/en-us/library/ms254947.aspx
SqlConnection sq = new SqlConnection(ConnectionString);
Reference
Done with "using" statement (from MSDN)
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Do work here; connection closed on following line.
}