Data First or Code First Part 2
With the Code-First approach, anytime we need to make changes to the database schema, we must implement the change in the codebase first. And one way to propagate that change to the database is by invoking the following 2 commands in the command line:
First command line:
dotnet ef migrations add <migrationName> -c <dbContextName> -s <projectName>
This command will add migration script file with the name YYYYMMDDxxxxx_<migrationName> inside the <projectName> project. Illustrated below is a highlighted example where we add an email address field in the owner table:
The DateTime stamp is very helpful to determine the sequence of the change. Along with a short description, which could also be a Jira ticket #, some kind of log id, or just a simple change name this migration naming convention is an excellent way of keeping track of the changes.
And the second command line for the migration process is:
dotnet ef database update <migrationName> -c <dbContextName> -s <projectName>
This command will actually update the database schema with the changes that were scripted in the migration script from the first command line.
It is customary to have two database environments for each solution: The development environment, and the production environment. One simple way to avoid the connection string being exposed in appSettings.json, is by setting up the two connection strings in the Startup.cs. And then use a conditional statement to select one or the other, depending whether we run the program in Visual Studio debug mode or have the server run the application in publish mode. The conditional statement would look something like this:
string connStr;
if (this._environment.IsDevelopment())
connStr = "devConnectionString";
else
connStr = "prodConnectionString";
And then we can use that connStr for setting up the DBContextPool like this:
services.AddDbContextPool<dbContextName>(options =>
{
options.UseSqlServer(connStr, b => b.MigrationsAssembly("<projectName>"));
}
});
Once the condition is setup and we successfully push our database migration changes to the development environment, we could comment out the if - dev block in that condition like this:
//if (this._environment.IsDevelopment())
// connStr = "devConnectionString";
//else
connStr = "prodConnectionString";
And rerun the second EF command line again:
dotnet ef database update <migrationName> -c <dbContextName> -s <projectName>
This would push the schema changes to the production environment.
As expected, the migration process for Code-First approach is the exact the opposite from Data-First approach. In Data-First approach, we would make changes in the database schema first. And depending whether we use ORM or in-house generated ADO .net calls, we would regenerate the entities and then adjust the code accordingly.
Code-First approach is a newer way of implementation, and it forces the developer to take seriously any changes that require database schema changes. Any schema changes in Code-First approach must undergo a more rigorous process, versus simply adding fields in the table using a database management tool such as SSMS, PhpMyAdmin, and others.
Good series of code first approach overview.