Reputation: 3954
I am using EF6 in a class library (database first)
When I followed the wizard and added my tables I selected not to store the connections string in the app.config and that I would send the connections string.
I haven't done this before. Normally I select to put the connection string in the app.config file.
I am now completely stumped how I actually call a function and pass the connection string to it.
Below are what I hope are relevant code snippets from my solution.
In the app.config - EF automatically added this:
<connectionStrings>
<add name="cerviondemoEntities" connectionString="metadata=res://*/DatabaseModel.cervionEDM.csdl|res://*/DatabaseModel.cervionEDM.ssdl|res://*/DatabaseModel.cervionEDM.msl;provider=System.Data.SqlClient;provider connection string="data source=DEVBOX;initial catalog=cerviondemo;user id=sa;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
My auto generated context class looks like this:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CervionFunctions.DatabaseModel
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class cerviondemoEntities : DbContext
{
public cerviondemoEntities()
: base("name=cerviondemoEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Ticket> Tickets { get; set; }
}
}
Ultimately, I am trying to call the following test function:
public static List<Customer> customersToUpdate()
{
cerviondemoEntities db;
using (db = new DatabaseModel.cerviondemoEntities())
{
var result = from customers in db.Customers
select customers;
return result.ToList();
}
}
I cannot work out how to send the connection string to that function.
Upvotes: 27
Views: 60476
Reputation: 831
I had this issue as well and used the method from Daniel in the comments.
Alternatively, you can add it to the .tt file instead of creating another file and using 'partial' – Daniel K Dec 9 '16 at 19:16
*Update .Context.tt File
just replace the lines...
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
with the following...
public <#=code.Escape(container)#>()
: this("name=<#=container.Name#>")
{
}
public <#=code.Escape(container)#>(String nameOrConnectionString)
: base(nameOrConnectionString)
{
Upvotes: 14
Reputation: 814
The problem with many approaches shown above (apart from Ian Covill) is that whenever some changes are made in the database and the corresponding model updated, all changes are lost (example, another constructor with parameter).
Hence, another approach, very similar proposed by Ian Covill, can be used. In my case, I have to choose between development and production database (identical ones).
In App.config or web.config
<add name="MyEntities" connectionString="metadata=res://*/Infrastructure.DAL.MyDal.csdl|res://*/Infrastructure.DAL.MyDal.ssdl|res://*/Infrastructure.DAL.MyDal.msl;provider=System.Data.SqlClient;provider connection string="data source=192.168.0.1;initial catalog=MyDBName;user id=user;password="password";MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
<add name="MyEntities_TEST" connectionString="metadata=res://*/Infrastructure.DAL.MyDal.csdl|res://*/Infrastructure.DAL.MyDal.ssdl|res://*/Infrastructure.DAL.MyDal.msl;provider=System.Data.SqlClient;provider connection string="data source=192.168.0.1;initial catalog=My_TEST_DBName;user id=user;password="password";MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Just Outside of *.edmx but on same folder, create a partial class having same name as EntityFramework entity name.
public MyEntities(string conStr) : base("name=" + conStr)
{
}
Now, we can pass our test or production database connection string name. Create a partial class (not necessarily) so that you can call this static method to get connection string for correct database based on pre-processor directive.
public partial class TestOrProductionDBSelector
{
public static MyEntities GetTestOrProductionEntity()
{
#if DEBUG
return new MyEntities("MyEntities_TEST");
#else
//ok without param as default is production
return new MyEntities();
#endif
}
}
Now, the static function GetTestOrProductionEntity() can be called from anywhere and it will call the appropriate connection string based on pre-processor directive selected.
Hopefully, this helps someone. The big advantage of this approach is the auto-generated *.Context.cs (inside *.edmx) will remain intact and risk of custom code inside it being overwritten is eliminated.
Upvotes: 0
Reputation: 1
So much better way to do this. The issue with any change of the diagram or properties the context.cs is rewritten. The clue is that all of the files are written as partial class objects. So, in order not to need to rewrite the context every time you change the entity framework, add a new cs file outside the EntityFramework edmx with a partial class with just the snippets discussed in previous posts.
public partial class cerviondemoEntities
{
public cerviondemoEntities(string connectionString):base(connectionString){}
}
This was kind of discussed in the most approved post, but it was easy to glance over. This should stop your code from not working if you change the EntityFramework properties. This was important to me because my application needed to connect to remote SQL databases.
Upvotes: 0
Reputation: 442
I have used the connection string like this, entity connection string instead of normal connection string
SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
{
DataSource = "SOURAV-PC", // Server name
InitialCatalog = "efDB", //Database
UserID = "sourav", //Username
Password = "mypassword", //Password
};
//Build an Entity Framework connection string
EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
{
Provider = "System.Data.SqlClient",
Metadata = "res://*/testModel.csdl|res://*/testModel.ssdl|res://*/testModel.msl",
ProviderConnectionString = sqlString.ToString()
};
return entityString.ConnectionString;
}
Upvotes: 4
Reputation: 608
By convention, Entity Framework takes the connection string that has the same name as the context. For example:
public cerviondemoEntities()
: base("name=cerviondemoEntities")
{
}
The DbContext class has a constructor that takes a connection string. You can add another constructor that takes a connectionstring as a parameter and pass it to the base constructor.
public cerviondemoEntities(string connectionString) : base(connectionString)
{
}
Be sure to create a partial class so your added constructor is not overwritten.
Sample ConnectionString:
<connectionStrings>
<add name="cerviondemoEntities" connectionString="data source=server\database;initial catalog=catalog;persist security info=True;user id=user;password=password;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
Upvotes: 45
Reputation: 49095
You need to introduce another constructor in your context that is expecting a string connectionString
argument and make it call base(string nameOrConnectionString)
:
public cerviondemoEntities(string connectionString) : base(connectionString)
{
}
Upvotes: 5