How does Package Manager Console know which connection string to use? - c#

I have a website application. Depending on the IsDemoSite setting in my appsettings.json file, the application uses one of two different database connection strings. (One for my main site, and another for our demo site.)
I also have a class library that contains all the Entity Framework models and migrations.
In the Package Manager Console, I set the Default project to the class library.
Then, I can run the add-migration and update-database commands on that class library. But here's the kicker: The IsDemoSite setting for my main application determines which database these commands work with.
How on Earth does Package Manager Console know to what connection string is used by my main application based on the current setting? I'm not running the main application. Package Manager Console is not using the main application as the default project. How the heck does it know which connection string to use?

When you run and add-migration or an update-database command, Package Manager Console will look for the Startup project of your solution and use it as "entry point" for these commands.
Probably inside your Startup.cs class you have the database context injected using the connection string that is stored in your appsettings.json.
I believe you have something like that:
string connectionString;
bool isDemoSite = configuration.GetValue<string>("IsDemoSite");
if(isDemoSite)
connectionString = configuration.GetConnectionString("mainSite");
else
connectionString = configuration.GetConnectionString("demoSite");
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(connectionString));
add-migration and update-database uses this very same code to determinate against which database it will execute, is something like your application is beign executed to allow this commands to run.
That's also the reason you need some EntityFramework packages installed in your startup project.

I was wondering which appsettings.json would the application use if i used Package Manager Console from Visual Studio 2022. I had appsettings.json, appsettings.Development.json and appsettings.Production.json, each with different connection string.
The one used was appsettings.Development.json.

Related

Where to put connection string when moving database code to separate assembly

I have a Razor Pages website application and I'd like to move my database code to a separate project/assembly, which is referenced from my main project/assembly.
Creating a new class project and moving the files from my Data and Model folders is straight forward. But I'm not clear on where my connection string goes (currently, it's in the appsettings.json for my main project).
How do I specify the connection string for my class library?
The connection string should be configured in the same project where the services connect to the DbContext, so you can leave the appsettings.json as-is.
It is the configuring project (the one that is setting up all the dependencies) that sets the connection to the DB, and the EF migration tool needs the connection to track and apply changes. Any assembly can be used to store migrations, but the EF tool needs to be invoked for a project with an actual connection.
EF Core uses Dependency Injection to configure services for runtime which includes setting the connection string for any DB. The control of how the DB classes interact with their environment is given to the app that is running it, which allows for the same DB code to be used across multiple instances, states and even providers. EF Core uses the current state & provider of the DB where it is deployed to determine changes and scaffolding, so it can only create migrations with a configured instance of a DbContext connected to a DB (usually the development instance).
When a solution is comprised multiple dependent services with a common data model that will need the same migrations, only one of the projects in the solution should be responsible for managing DB state. Whichever project is chosen, it needs to create a DBContext with a valid connection when it starts up for the EF tools to work. ASP.NET Core uses the Microsoft.Extensions.Configuration package and the UseStartup method to make the configuration simple. This can be your existing UI project that would read the connection string from existing settings and pass it to your CustomDbContext at Startup. The EF Tools CLI will use the default profile (the Green run arrow) to get the settings from launchSettings.json and appSettings.json to connect to the DB. The configuration should be in place in each environment you deploy to so that the migrations can be run from the same configuring project and applied as needed.
You can avoid ASP.NET and create a custom startup class in your data package that runs to apply migrations, but this is a lot of extra work for something already in the box. The DbContext class does have an OnConfiguring method that can be used to set the connection. Placing configuration inside of code limits where the software can run, so it should still be set externally.
The DbContext can be referenced from another package:
The DbContext and Models can be defined in a separate 'pure' project, then referenced in the Startup like so:
using mysolution.Data.CustomDbContext;
...
services.AddDbContext<CustomDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("defaultConnection")));
Configure the DbContext to run and where to store migrations:
The tricky part is applying migrations if you use them. If your Razor assembly was named 'mysolution_UI' and your data project is 'mysolution_Data'. Move the Data, Models, Migrations to mysolution_Data and add this to the startup in mysolution_UI project:
services.AddDbContext<CustomDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("defaultConnection")
, b => b.MigrationsAssembly("mysolution_Data")));
Then when adding or deploying the package, the migrations should be invoked from the 'mysolution_UI' project.
Add-Migration NewMigration -Project mysolution_UI
This allows multiple projects to use the data package for the entities connected to the same DB, but only one is responsible for maintaining the migrations.

WCF Connected to Entity Framework (Cannot Attach)

I'm using Entity Framework with code-first migration, but after adding a new project to my solution for a WCF service, I get the following error when attempting to run update-database:
Cannot attach the file ...App_Data\MyProject.Data.MyDbContext.mdf'
as database 'MyProject.Data.MyDbContext'.
I've following projects:
MyProject.Data
MyProject.WCFService
The currently temporary solution to this problem is to stop and remove the local db. But why do I need to this, what am I missing? It have worked before without this.
Developer Command Prompt for Visual Studio:
sqllocaldb.exe stop v11.0
sqllocaldb.exe delete v11.0
In Visual Studio:
Update-Database
When you run update-database, code first migrations will attempt to use the connection string from your current start-up project configuration file to connect to the database and perform updates. The easiest way to resolve this in your case sounds like it would be to copy the connection string from your MyProject.Data configuration file to your MyProject.WCFService configuration file. You can also try setting MyProject.Data to the start-up project for your solution, or you can override the parameterless constructor from DbContext in your derived DbContext class and specify an explicit location for a connection string (such as the registry).

Is code first migration automatically run on the server?

I am very familiar with Entity Framework using Database First approach and how to deploy the solution with it.
Basically, in my solution with database first approach, I have a web client project that consumes data access library project that is coded with database first approach.
So, first, I write some SQL Server scripts to add new tables (or make schema changes).
Next, go to the data access library project, using EF edmx designer to update .net from existing database, compile this data access layer, and the DDL reference is automatically updated in the client web project.
When I deploy the solution to the production server:
First, I need to run the t-SQL scripts on the production SQL server
Next, I deploy the 2 updated DDLs (one for the web and 1 for the data access layer) on the web server.
Now, I have a new application that includes a web project and a data access layer project that uses EF Code First approach.
I am new to EF code first approach. I know any time when I change the database schema, for instance adding a new table, I need to run code first migration in the Package Management Console in Visual Studio to let my back-end database instance change/update.
My question:
When I deploy the application to the production, what are the steps I should follow?
How is the production SQL server updated that is created with EF Code First approach?
Is it a automatic process or I have to run the migration manually like I do inside Visual Studio under the Package Management Console?
Thanks.
If you're using Azure then you can configure it has automatic process as shown below.
Else you have to do it manually like this :
You have to create a db script and after that you can run it on your production db.
PM> Update-Database -Script
You can refer this doc : Getting a SQL Script
Another option where I normaley use :
When I need to run migrations aginst the production db,I change my conn string to reflect production db and after that run :
PM> Update-Database
You have several options with migrations.
You can generate a script using Update-Database -Script (as #Sampath notes)
You can run Update-Database -ConnectionString="YourDbString" and it will do it against the production database for you
You can use a migration initializer and on app startup it will use the applications connection string to run the migration. Do this by putting a line similar to this in your initialization routine:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());
Where Context is your DbContext type and Configuration is the configuration class generated when you made the first migration.
See this MSDN article for more information: https://msdn.microsoft.com/en-us/data/jj591621.aspx

How to change database after altering model in MVC?

I'm new to ASP.NET and I'm working on this project that uses MVC. It's a simple website development project, and it uses SQL Server CE (.sdf) as the database.
I would like to change a couple of the underlying models, but that causes errors in the database.
I understand that I would need to change the database, and I know it's possible to create models automatically from the database.
I'm wondering if there is any way to create a database from the models. i.e. I don't mind losing all the data, but is there a way for me to change the models and then create a database that supports the existing models.
I hope that makes sense
Yes it possible to
Here is how you can do it.
There are two approaches to accomplish this task.
Method-1. (Via Package Manager Console)
This approach for the Code First.
Open your project and go to Package Manager Console as follows
Tools--> Nuget Package Manager--> Package Manager Console
First Enable Migrations in your project.Type following in console.
enable-migrations -contexttypename yourContextName
This command will add a Migrations folder in your project inside this folder you will
see Configuration.cs inside this file you will see a seed method
protected override void Seed(YourContext context)
you can use this method to seed your database.
Now run following command in your package manager console
add-migration anyNameOfInitialMigrations
Finally To update the database simply run following command.
update-database
Method-2.
Best approach for Model First.
Open your .edmx file.
Right Click--> on the model and then select "Generate Database From Model"
Make Sure you have proper connection strings in your web.config.

How to enable Code First Migrations in ASP MVC app?

I have ASP.NET MVC4 app with Entity Framework Code First approach. I've moved my DbContext inheritor to separate Model project recently (I've copied connection string from web.config to the app.config).
Now when I'm trying to run my app I've got error that my database should be created directly through Code First or Migrations. First way is not suitable for me because I have remote DB server (I've created it through hoster's control panel).
But when I'm trying to enable Migrations I've got error that No context type was found in the assembly 'MyProject'. This is obviously happen because my DbContext inheritor not placed in the start project.
So how can I indicate to look context class in separate project?
By the way, I have DropCreateDatabaseIfModelChanges<> initializer for my DbContext inheritor.
In the Package Manager Console, if you run Get-Help Enable-Migrations, it will show you all of the advanced options. Included in those are:
-ProjectName (the project to run this command against, i.e. to look for the context type)
-StartupProjectName (the project which has the app.config/web.config where the context runs, i.e. where your connection string lives). This one is important unless your Model project has the correct connection string in its own .config file.
-ConnectionString (the connection string to use while scaffolding the migration if you want to override the value)
When you're using Add-Migration it should support the same options.
You can also change the Package Manager Console's Default Project dropdown to run against your model project by default.
If you are using Package Manager Console you can choose a default project where entity framework will search your DbContext.

Categories

Resources