EF6 Change connection string at runtime - c#

I created a EDMX file from DB:
internal partial class LocalBDD : DbContext
{
public LocalBDD() : base("name=LocalBDD")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<C__RefactorLog> C__RefactorLog { get; set; }
}
If I store the connection string in App.config, this works fine, but I need to encrypt the sensitive info, I'm trying to change the connection from my context in this way:
LocalBDD _localBDD;
_localBDD = new LocalBDD("my new connStr");
But I get
LocalBDD does not contain a constructor that takes 1 arguments
This code it's generated by the ADO.NET Entity Data Model Assitant, and if I edit it for add a constructor which takes 1 argument, when the project recompile the changes will be lose.
How I can change the connection string of my DbContext at runtime?
Thanks in advance

I highly recommend that you read some basic C# tutorials on classes and constructors, which would help you understand the error you are receiving.
Your LocalBDD class constructor only takes one argument. If you want to be able to pass in connection string information, you need to either expand your current constructor or add an additional constructor with a string argument:
public LocalBDD()
: base("name=LocalBDD")
{
}
public LocalBDD(string connectionString)
: base(connectionString)
{
}

Based on David's response I created a separate .cs file and wrote in this a partial class to prevent the overwriting:
public partial class LocalBDD : DbContext
{
public LocalBDD(string connetionString)
: base(connetionString)
{
}
}
However I´m not sure this is the better way. Thanks to both of you.

Related

How to change the database name in Entity Framework

I'm trying to find a way to change the database name in my web.config and my context. No other info in my connection string changes but the database name.
public APIContext(string dbname = "MyFirstDB") : base("OriginalContext")
{
this.Database.Connection.ConnectionString = this.Database.Connection.ConnectionString.Replace("MyFirstDB", dbname);
}
The only way I can find to achieve this is to replace the name, but I can see few problems in the future, for example if I need to go back or need to point to another database. Using mysql.
Any help will be appreciated.
** EDIT **
[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))]
public class APIContext : DbContext
{
public APIContext() : base("MyContext")
{
}
public void setDatabaseName(string name)
{
var currentdatabase = this.Database.Connection.Database;
this.Database.Connection.ConnectionString = this.Database.Connection.ConnectionString.Replace(currentdatabase, name);
}
Would this work if I were to call the "setDatabaseName(string name)" method before I call my context class?
I'm just confused on where I should be replacing the database name and how to do it.
Have you tried this?
public partial class MyModel : DbContext
{
public MyModel()
: base("name=MyModelDataContext") // <-- ConnString Name
{
}
}
And your connstring looks like this
<add name="MyModelDataContext" connectionString="data source=... initial catalog=YOURDB
This way you can change your db name any time.
this is actually how the code first from database wizard generates it
Ok, if you want to use more than one connstring you can do this
public class MyModel : DbContext
{
public MyModel ()
: base(ApplicationParameters.ConnectionStringName)
{
}
public MyModel (string connectionStringName)
: base(connectionStringName)
{
}
}
Then in your web.config you can set a list of connstrings and in your code you can call any of them with the second constructor.

How to set the name of ConnectString dynamically in asp.net MVC 5

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);

How to Embed Entity Framework in a Class Library

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. :)

The best way to swapping connectionString parameters on runtime

I have a class generated by EF.
public partial class AMIEntities : DbContext
{
public AMIEntities()
: base("name=AMIEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<AMI_DATA> AMI_DATA { get; set; }
public DbSet<AMI_DATA_HISTORY> AMI_DATA_HISTORY { get; set; }
}
In the app.config file in the connectionString I store the encrypted password to MSSQL server. Where can I add code to replace the connectionString for all calls in your application without changes already created the code?
using (var context = new AMIEntities())
{
var test = context.TABLE.ToList();
}
What is the best way?
Although I absolutely hate working on generated code you can add the following constructor to your AMIEntities class.
public AMIEntities(string connectionString)
:base(connectionString)
{ }
you can then swap out your connection string in runtime to access another database, e.g.
using (var context = new AMIEntities(your_New_ConnectionString))
{
var test = context.TABLE.ToList();
}
Note: you are going to have to pass through either an EF connection string or you have to build a new EF connection from a simple connection string.
UPDATE
For the purposes of retaining your code change even when the generated code is re-generated, you can create a class that inherits from your AMIEntities class and set your constructor there, basically:
public class AMIEntitiesExtended : AMIEntities
{
public AMIEntitiesExtended (string connectionString)
:base(connectionString)
{ }
}
and then call your new class instead of the generated class:
using (var context = new AMIEntitiesExtended(your_New_ConnectionString))
{
var test = context.TABLE.ToList();
}

Merge routes in servicestack

I have a Dto like this:
[Route("/clients/", HttpMethods.Post)]
[Route("/clients/{Dummy}", HttpMethods.Post)]
public class ClientPostDto : IReturnVoid
{
public string Dummy { get; set; }
}
And the post method in my service:
public class ClientService : Service
{
public void Post(ClientPostDto request)
{
// do some stuff
}
}
Is it possible to merge these two routings?
So the following two POST request are handled by the same Method in my Service:
localhost:12345/clients/
localhost:12345/clients/CLIENT_IDENTIFIER
I won't need the Dummy property at all, because the clients are stored in a list with the full path.
You can use the magic {ignore} literal instead, i.e. if you want to specify a wildcard without needing to specify an existing property, e.g:
[Route("/clients/{ignore}", "POST")]
public class ClientPostDto : IReturnVoid {}
That should just work. But you should keep the dummy variable so you know what has been requested perhaps retitled to ClientIdentifier.

Categories