Quick Notes: EF Core Tools (VS)
Quick Notes: EF Core Tools (VS)
** Brackets should not be included, they indicate a parameter. **
These commands work in visual studio. The CLI tool has slightly different arguments.
Migrations:
- Add Migration: Add-Migration <migrationName> - will build the project, then create a migration file for the set of models. NOTE: If build fails, this will not work. Program must be compilable for this to work.
- Remove Migration: Remove-Migration - will remove the last migration.
Database:
- Update Database:
- Update-Database - this will update the database to the current Migration file (I believe it "plays" the migration files after checking the DB migrations table for what's missing).
- Update-Database <MigrationName> -this will downgrade a server to a specific migration
- Update-database -Migration 0 - This will basically remove all applied migrations (and migration created tables) from the server
- The name of the created tables will match the names of the properties defined in you DBContext class. For example a property defined:
DBSet<Type1> Type2 {get;set;}
would end up with a database named Type2.
Foreign Keys:
EF tooling will also auto-handle foreign key constraint creation and insertion on nested model collections within a model. Suppose you have a Vendor class with a list of Addresses:
public class Vendor
{
public int VendorId {get; set;}
public string VendorName {get; set;}
public List<Address> Addresses {get; set;}
}
public class Address
{
public int AddressId {get; set;}
public string Street1 {get; set; }
public string Street2 {get; set; }
public string City {get; set;}
public string State {get; set;}
public string Zip {get; set;}
}
When you build the migration it will create a foreign constraint on the addresses table, and add the key field from the vendor class to the database (so that the Addresses table will have a "VendorId" field). And when you use the DB context to add a vendor, it will automatically insert that vendor's addresses into the addresses table. Manual naming of the foreign key field can be controlled in 2 ways (in the above example, let's say we want to use "VendorIdentity").
- From the primary models navigation item (in the above case the Addresses field in the Vendor class) would have the Data Annotations Attribute of:
[ForeignKey("VendorIdentity")] - From the secondary model's existing field (in the above case, we should be able to add the field VendorIdentity with this attribute:
[ForeignKey("Address")]
public int? VendorIdentity {get; set;}
NOTE: I've had issues with this were it was seemingly ignored and used the first method mentioned.
The default foreign key mapping may not be desired if you are wanting to use a generalized Key that happens to span multiple tables (suppose you want a contact key that might be a vendor key, a customer key, or an employee key). It's possible that this could be done with the ForeignKey attribute on the parent table navigation item, but I've not had the pleasure of trying this yet.
Note that models don't need key field or foreign key field attributes if the key fields follow the guideline of ModelNameId (this is assumed to be the key field and should be the foreign key of secondary tables).
Compound keys are supported, but have their own nomenclature. Make sure that the "order" matches between primary and secondary tables for these.
Play Book/Issues
- Scenario: DB can't make key field changes on Update DB command after you changed key attributes or identity attributes in your model class. In this case, use the "Remove Migration" command repeatedly until your migration files are empty (or until it is appropriate). Then run "Update-database -migration 0" to wipe out the database. Finally, re-add a migration with something like "Add Migration NewStructureChanges" and finally "Update-Database".
WARNING - this is data destructive and should be performed in your dev environment. If you happen to be doing this directly in Prod and you don't want to lose the data, backup the data for reimport. - General approach for downgrading: first, downgrade the DB to the desired target, then remove the migrations after the desired point (remove-migration until the target migration is the most recent).
- If the during migration changes, the DB starts to complain on the change based on the contents of the table (perhaps due to changes in key constraints), try taking a backup of the problem table and truncating the data. To get the data back in, you may save it out as a flat file that you can alter as needed, and then do a reimport after the migrations have been applied correctly. This should be done in your dev environment first, and may give you clues about potential issues you could run into pushing into production. If there are changes from prior migrations that are causing issues that were sorted out, you can remove those migrations and roll changes up into one single migration with "add-migration" command once the errant migrations are removed (DB must also have appropriate deployment level).
- If you have side loaded lookup tables that you may not want in your models (suppose they are tables needed for reporting and not application logic), Entity framework does not mess with those. It appears to abide with "undoing" the changes made specifically by the down sections of the migration files. So as long as those tables weren't created through migrations, you should be fine. If, however, you add a column directly to a table that was created by migration, you are best off to define it in migrations because downgrading to a migration prior to that table will remove that column and you may forget about it. This scenario also seems to indicate other projects could potentially play in the same database but i have questions on this:
- Is there a single EFMigrations table for both/multiple projects?
- What happens if 2 projects have alterations for the same table?
- What are Microsoft's recommendations for this? It seems like the best approach is to only use this in an individual sandbox/dev environment and copy the database into a shared prod/staging environment.
5/05/2025 - updated section for foreign keys and note about lookup tables issue.
5/06/2025 - corrected statement in very last section
5/08/2025 - notes on side loaded tables/columns added.