The best way to swapping connectionString parameters on runtime - c#

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

Related

Coming from EF to EF Core, how do I use the using statement correctly?

I must be doing something wrong in my context I have my context below which I want to wrap up in my manager class. And I want to be able to use the using statement so that my context is used only once.
public class xxxDbContext : DbContext
{
public xxxDbContext(DbContextOptions<xxxDbContext> options)
: base(options)
{ }
public DbSet<JobsList> JobListingss { get; set; }
public DbSet<Clients> ClientListings { get; set; }
public DbSet<Engineer> EngineerListing { get; set; }
public DbSet<Case> CasesListing { get; set; }
}
But when I want to use my context in my using statement such as
public class xxxContext
{
xxxDbContext _db = new xxxDbContext();
public List<Case> GetAllCases(int databaseId)
{
List<Case> q = new List<Case>();
using (var myContext = new xxxDbContext(what must I reference here ?)))
{
q = myContext.Cases
.Where(w => w.databaseID == databaseId)
.OrderBy(o => o.CustomerName).ToList();
}
return q;
}
}
Before I was just able to make a parameter less construct can I do same here for core or does that override what is meant to be done.
Also what is best practise should I have a separate class for all these functions or should I have a partial class based on my context?.
You will need to use the DbContextoptionsBuilder<T> generic class to get the instance of options back:
var optionsBuilder = new DbContextOptionsBuilder<xxxDbContext>();
and now you will have to use the created instance to be passed in the constructor:
using (var myContext = new xxxDbContext(optionsBuilder.Options)))
{
// code here
}
EDIT:
So what you need is first of all configure a service in services for getting the Options like:
public void ConfigureServices(IServiceCollection services)
{
// using sqlite as example via official docs example
services.AddDbContext<xxxDbContext>(options => options.UseSqlite("Data Source=blog.db"));
}
and then in the code where required to create the dbContext you could resolve it like:
var options = serviceProvider.GetService<DbContextOptions<xxxDbContext>>();
and now pass it to the Context class object creation time in constructor:
var options = serviceProvider.GetService<DbContextOptions<xxxDbContext>>();
using (var myContext = new xxxDbContext(options)))
{
// code here
}
You can refer to the following post for details at official docs:
Configuring a DbContext

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

C# WCF - ADO.NET Entity model - DbSet empty?

I created a new WCF project in visual studio based on a existing database.
I made two operations. One operation writes a record (createProfile) to the database and one retrieve data (GetProfiles). My project exists of 3 files: web.config, a edmx file and my svc class.
CreateProfile works fine, I checked in SQL and the record is created.
GetProfiles never gives a response. When I debug the context.UserProfileSet always counts 0 values.
Any suggestions on what is going wrong?
[DataContract]
public partial class UserProfile
{
public int Id { get; set; }
[DataMember]
public string UserName { get; set; }
}
public class MusicOwnerService : IMusicOwnerService
{
IEnumerable<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.AsEnumerable();
}
}
public void CreateProfile()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
context.UserProfileSet.Add(new UserProfile { UserName = "John" });
context.SaveChanges();
}
}
}
As far as I know, you cant pass an IEnumerable object over the wire with WCF (unless youve a duplex binding of some sort??).. so you would be best to convert to a list and return that list like below:
List<UserProfile> GetProfiles()
{
using (MusicOwnerDatabaseEntities context = new MusicOwnerDatabaseEntities())
{
return context.UserProfileSet.ToList();
}
}

Categories