I want to wrap some queries in a SharedDbConnectionScope and execute them under a different connection string. How do I add a provider/connection string dynamically in order to do this?
Thanks
Both the ActiveRecord\Context.tt and the LinqTemplates\Context.tt that you would use to generate your classes contain constructors:
public <#=DatabaseName#>DB(string connectionStringName)
{
DataProvider = ProviderFactory.GetProvider(connectionStringName);
Init();
}
public <#=DatabaseName#>DB(string connectionString, string providerName)
{
DataProvider = ProviderFactory.GetProvider(connectionString,providerName);
Init();
}
So you can pass your connection string to one of these constructors, like:
// point to a certain connection string in the app.config
var db = new MySample("SomeConnectionStringName");
// Use a specific connection string, not the app.config
var db = new MySampleDB(#"server=.\SQL2008;database=Sample;integrated security=true;", "System.Data.SqlClient");
Related
I have the following problem: My Program uses an .EDMX model generated from a SQL database with EF on the .NET framework.
When I work on the program at home from my desktop PC, I use Windows authentication. When I open the program at work, it is necessary to build a new .EDMX model with new PC name and standard SQL Server authentication.
How is it possible to change the connection string with a login window for example where I can chose user name, server name and DB name. MS Documentation is not a Help
Thanks for your help
First, you can define the helper to generate a runtime connection string for EDMX. you can find more options for your connection here
public static class Helper
{
public static string GenerateConnectionString(string server, string database, string username, string password)
{
return $"data source={server};initial catalog={database};persist security info=True;user id={username};password={password};" +
$"MultipleActiveResultSets=True;App=EntityFramework"";
}
}
Then add contractor for EDMX Model, for example, my Context model name is [banescoEntities]. "for find context you can type EMDXModelName and use F12 for go to DbContext". shown location on pic. But be careful if you rebuild Model Context, Mabe needs to rewrite code
public partial class banescoEntities : DbContext
{
// add this constractor
public banescoEntities(string connectionString)
: base(connectionString)
{
}
public banescoEntities()
: base("name=banescoEntities")
{
}
// other Context items
}
then create instance like :
internal class Program
{
static void Main(string[] args)
{
// generate ConnectionString runtime
var cs = Helper.GenerateConnectionString("172.31.4.24\\MSSQLSERVER2019", "banesco", "sa", "blablabal");
banescoEntities bsEntities = new banescoEntities(cs);
var products = bsEntities.Products.ToList();
}
}
I have a connectionString as follows:
<add name="EDentalCADBContext" connectionString="data source=*.*.*.*\SQLEXPRESS;Initial Catalog=*******;User id=*****;Password=******;" providerName="System.Data.SqlClient" />
I created the same ConnectionString dynamically, but I am unable to set the name of the ConnectionString such as name="EDentalCADBContext" in above.
How can I set the name dynamically?
Thanks
I agree with #Dai above. If you are creating it dynamically in the code, then what's the point of putting into a configuration wrapper. Why not just use it directly? The point of that entire interface is really to read stuff out from the common .config files.
Nevertheless, it is possible to do. When you create a ConnectStringSettings instance, you pass 'name' and 'connectionString' in the constructor: https://msdn.microsoft.com/en-us/library/wd8h82yf(v=vs.110).aspx
EDentalCADBContext context = new EDentalCADBContext();
public ActionResult Masters(int? pageNumber, string tableName)
{
EstablishConnection(); // This creates the connection with DB dynamically.
int? page = 1;
ViewData["MenuItems"] = MenuItem.ActivateMenu("Masters");
ViewData["Users"] = context.Users.ToList();
}
public class EDentalCADBContext : DbContext
{
// public EDentalCADBContext() : base("EDentalCADBContext") { }
public DbSet<NotificationItem> NotificationItems { get; set; }
public DbSet<User> Users { get; set; }
It is expecting EDentalCADBContext name of the connection string. Why should it match?
I'm stabbing in the dark without knowing specifically how the rest of your code works. But you asked me to try, so here's my best go...
If you have your own custom class inheriting from DbContext then you have to implement your own constructor to take in the connection string. You don't get to inherit non-default constructors. So I've modified your class below to have a constructor to take in the string:
public class EDentalCADBContext : DbContext {
public DbSet<NotificationItem> NotificationItems { get; set; }
public DbSet<User> Users { get; set; }
public EDentalCADBContext(string connectionNameOrString) :
base(connectionStringOrName) {
}
}
You would instantiate like this:
EDentalCADBContext context = new EDentalCADBContext("literal conn string");
// Perhaps comes from sqlBuilder.ConnectionString per your comments?
In your comment, you wrote
I dont want to use ConnectionString from web.config. I created it dynamically. So I need to set the name to match it with DBContext
The solution is not to match the "magic string" that the DbContext expects (I imagine this was specified when you used the EF wizard in Visual Studio) but instead use the DbContext constructor that accepts a raw connection string:
String connectionString = "server=dbserver.local;Integrated Security=SSPI;...";
using( DbContext db = new DbContext( connectionString ) ) {
// do stuff
}
public EDentalCADBContext(string con = null)
: base(string.IsNullOrEmpty(con) ? "name=EDentalCADBContext" : con)
{
}
In your EDentalCADBContext context class.
Then when you instance this EDentalCADBContext you passing a Connection string as parameter.
Ex. EDentalCADBContext db = new EDentalCADBContext(Connection string);
I want to embed my entity datamodel to my class library that contains methods of database operations. (like MyEntityDatamodel.dll) Simply when i add my entity framework embedded class library to my windows forms application, i am able to use it's methods (insert update delete).
Currently i am able to running methods from dll but the problem is i must add EntityFramework.dll and EntityFramework.SqlServer.dll to my forms application as reference. Otherwise it doesn't work. I want to add only MyEntityDatamodel.dll.
Sample code of my entity datamodel class:
public class MyClass
{
public string classParameter { get; set; }
public void InsertMethod(MyClass parameter)
{
var dbContext = new MyEntities();
InsertOperations...
}
public void UpdateMethod(MyClass parameter)
{
var dbContext = new MyEntities();
UpdateOperations...
}
}
How I am using;
using MyClass;
MyClass myClass = new MyClass();
myClass.classParameter = "example";
myClass.InsertMethod(myClass);
Thanks in advance.
Two things to note...
First, directly to your question - you can't. You may try some sophisticated techniques like dynamically loading the assemblies your program needs, but this changes almost nothing except that you do not have them listed in your project references. They still need to be somewhere where the loader can find them. And more important they must always be deployed together with your app. Otherwise it won't work.
Second, DbContext is meant to be used as a Unit-of-Work design pattern, that is it needs to be disposed after the unit has finished whatever it was meant to do. Usualy, the using clause is a very good choice for this, so consider wrapping your code this way:
using (var dbContext = new MyEntities())
{
InsertOperations.../UpdateOperations...
}
After spending hours of on this, finally i found a solution. I am able to inject connection string to my dbcontext before my dbcontext object was created.
First, i changed my dbcontext's constructor method. I added string parameter for connection string instead reading from the web.config.
I changed this;
public partial class ExampleEntities : DbContext
{
public ExampleEntities()
: base("name=ExampleEntities")
{
}
}
To this;
public partial class ExampleEntities : DbContext
{
public ExampleEntities(string connStr) : base(connStr)
{
}
}
Then i added a method for Generating connection string to my code;
public static string CreateConnStr(string dataSource, string instanceName, string userName, string password)
{
string connectionString = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder
{
Metadata = "res://*/ExampleModel.csdl|res://*/ExampleModel.ssdl|res://*/ExampleModel.msl",
Provider = "System.Data.SqlClient",
ProviderConnectionString = new System.Data.SqlClient.SqlConnectionStringBuilder
{
InitialCatalog = instanceName,
DataSource = dataSource,
IntegratedSecurity = false,
UserID = userName,
Password = password,
}.ConnectionString
}.ConnectionString;
return connectionString;
}
Now i am simply use my dbcontext shown as below;
var dbContext = new ExampleEntities(CreateConnStr("localhost\\SQLEXPRESS","ExampleDataBase","UserName", "Password"));
Hope it helps.
P.s.: Sorry for bad grammar. :)
I have an application using MSSQLSERVER,when I deploy it to the customer, the server name could change, so I have to change the connection string of my xpo data model at run time,
this is the class generated with the XPO data model
public static class ConnectionHelper {
public const string ConnectionString = #"XpoProvider=MSSqlServer;data source=localhost;integrated security=SSPI;initial catalog=tkdoc";
public static void Connect(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
XpoDefault.DataLayer = XpoDefault.GetDataLayer(ConnectionString, autoCreateOption);
XpoDefault.Session = null;
}
public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption);
}
public static DevExpress.Xpo.DB.IDataStore GetConnectionProvider(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption, out IDisposable[] objectsToDisposeOnDisconnect) {
return XpoDefault.GetConnectionProvider(ConnectionString, autoCreateOption, out objectsToDisposeOnDisconnect);
}
public static IDataLayer GetDataLayer(DevExpress.Xpo.DB.AutoCreateOption autoCreateOption) {
return XpoDefault.GetDataLayer(ConnectionString, autoCreateOption);
}
}
I'd like to change the ConnectionString in case the server or the user name or the password change
I suggest that you store the connection string in the application configuration file. This way, users can manually modify it, or you can provide them the special settings form for this purpose.
It is easy to read the connection string from the application configuration file. The code example can be found here on StackOverflow: Get connection string from App.config
How do I create connection string programmatically to MS SQL in Entity Framework 6?
I'm using c# and WPF and I was wondering if someone could show me how or link me to a resource that shows how to set up connection strings programmatically in EF 6. The MSDN article explains that you can http://msdn.microsoft.com/en-us/data/jj680699#moving but it doesn't go into creating actual connection strings.
So here is an EF6 example that works
App.Config
entityFramework codeConfigurationType="WPFwithEF.SqlConfiguration, WPFwithEF">
/entityFramework
context
public class ProductContext : DbContext
{
public ProductContext():base("Wpf")
{ }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
}
Configuration.cs
namespace WPFwithEF
{
public class SqlConfiguration : DbConfiguration
{
public SqlConfiguration()
{
SetProviderServices(SqlProviderServices.ProviderInvariantName,SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
}
but if the context base is "name=Wpf" then this set up does not work is there a way to make that work? And i'm looking for the latest EF6 not the old way to do it.
You can use the EntityConnectionStringBuilder as descriped here: How to: Build an EntityConnection Connection String
If you are specifically connecting to a MS Sql database, this should work:
private DbConnection CreateConnection(string connectionString)
{
return new SqlConnection(connectionString);
}
private string CreateConnectionString(string server, string databaseName, string userName, string password)
{
var builder = new SqlConnectionStringBuilder
{
DataSource = server, // server address
InitialCatalog = databaseName, // database name
IntegratedSecurity = false, // server auth(false)/win auth(true)
MultipleActiveResultSets = false, // activate/deactivate MARS
PersistSecurityInfo = true, // hide login credentials
UserID = userName, // user name
Password = password // password
};
return builder.ConnectionString;
}
how to use:
public void ConnectoToDbWithEf6()
{
using(var connection = CreateConnection(CreateConnectionString("server", "db", "you", "password")
{
using(var context = new YourContext(connection, true))
{
foreach(var someEntity in context.SomeEntitySet)
{
Console.WriteLine(someEntity.ToString());
}
}
}
}
see https://msdn.microsoft.com/en-Us/library/system.data.sqlclient.sqlconnectionstringbuilder%28v=vs.100%29.aspx
I previously used the DefaultConnection string found in the app.config ( or web.config) as example and just replaced the "connectionstring" on the DbContext, to the one i wanted.
The connectionstring looked something like :
Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-ShoppingList.Web-20150903103641.mdf;Initial Catalog=aspnet-ShoppingList.Web-20150903103641;Integrated Security=True
If i'm remembering correctly, you should replace the connectionstring in :
DbContext.Database.Connection.Connectionstring
PS. You can only use it this way if you are using Code-First. If you are using Model-First or Database-First you should use the EntityConnectionStringBuilder .
I investigated this question today. in my opinion the easiest solution is not mentioned above.
Why not use the SqlConnectionStringBuilder class? (using System.Data.SqlClient)
Here a simple example how to use it.
SqlConnectionStringBuilder sqlb = new SqlConnectionStringBuilder(getConnectionString(DATABASENAME);
using (SqlConnection connection = new SqlConnection(sqlb.ConnectionString))
...
)
// works for EF Core, should also work for EF6 (haven't tried this)
private static string getConnectionString(string databaseName)
{
return "Data Source=SQLSERVERNAME;Initial Catalog="+databaseName+";Integrated Security=True";
}
You could use the ProductivityTools.ConnectionString nuget package. It has 3 methods:
Creates connection string to server without database name
Creates connection string to server with the database name
Creates connection string for EntityFramework database context
Last method will be right for you and asssuming that your edmx is named Product after invocation
ConnectionStringHelper.ConnectionString.GetSqlEntityFrameworkConnectionString
("serverName", "databaseName", "Product");
Package will return:
metadata=res://*/Product.csdl|res://*/Product.ssdl| res://*/Product.msl;
provider=System.Data.SqlClient;provider connection string="Data Source=serverName;
Initial Catalog=databaseName;Integrated Security=True"