These are my notes while reviewing the latest release of Entity Framework EF6
Migrations = creates or updates database automatically as models in the application change. This lets developers focus on the application models and not worry about the database.
This does the actual SQL command execution. It is the last step of the EF workflow.
There are two types of models
- Database first
- Edmx (entity data model and extra xml)
- This is gernerated by the EF wizard tool
- Code First
- EF will generate the in memory runtime metadata
This is the only method that allows database migration (going from code to database) Note there are some conventional mappings used for this method, for example:
- Table names map to class names
- Column names map to class attribute names
Code Based Model and Database
LocalDB is a lightweight SQL Express database used by Visual Studio for development. This is the default database used by Entity Framework.
Extend this to use EF. This is part of System.Data.Entitty. The main data context used in app should extend this. Within this class, define the DbSets, or repositories, of the database. This can be
seen below. Also, the example below overrides the SaveChanges() method of DbContext to have some custom functionality (for tracking modification dates).
This is basically the repository that EF uses.
Validating EF Models
Use the Entity Framework Power Tools to be able to validate EF models
Not having Foreign Keys in EF Models
EF Models should explicitly define foreign keys. This will save in performance. In the example below, the ClanId foreign key is kept in the Ninja model that relates to it:
Code First Migrations to Create a Database
To do a database migration must have a class that extends DbMigrationsconfiguration() from entity framework. This class would have a seed method to do the initial seeding of the database. Also, ensure that the AutomaticMigratoinsEnabled is set to false.
There are 3 steps to the code first migration process:
- Define / Change model
- Create a migration file
- Apply the migration to the database
The commands for these are done in the package manager console:
PM> add-migration // name
The above commands will create the migration class. In it are the commands to create the tables in the database:
The next and final command is:
Another command to run is:
PM> update-database -script // creates scripts only
PM> update-database -verbose
Migrating Database when Models change
We can do incremental updates to database from models by the same command. Note that this creates to the new migration file called update, instead of initialMigration which is what it did above.
PM> add-migration updateMigration
This command creates the new updateMigration files. To run the actual migration, run the command:
PM> update-database -verbose
Interacting with EF for data
Adding data through .Add() function. The following example logs the action of adding the new ninja object. Note that the context is NinjaContext, which was extending DbContext. The Add() method only allows addition of single record at a time. The AddRange() method allows multiple additions at a time.
To Query, we use LINQ. There are two ways to do this, LINQ Methods and LINQ Query Syntax
Context.Ninjas.Where(x => x.Name == � � � ).ToList();
LINQ Query Syntax
(FROM ninja IN context.Ninjas WHERE ninja.Name == �xx� �)
Note that queries can be done in enumerations � but this keeps database connection open until that loop completes. So it is bad practice. Better to call / execute query up front into a variable and then loop through that variable.
The following is example of updating. Entity framework is smart enough to only update those records that have changed. So in the first method below, the SQL only written for the �ServedInOniwaban� value and ignores everything else since that�s all that changed.
Note that in the second method below, we are instantiating a new context. In doing this, the second context doesn�t know what the first context did. To get around this, that second context must define the state for that ninja instance as being modified. The other way to do this Is to just use the same context, as shown in the first method.
A quick way of query an object with the key value. This will check in memory first (within it�s context) and if not found, will go out to the database. Note that in example below, the second .Find() method call will not doing anything because Entity Framework already did the query above it and knows to just reuse that.
There are a few ways to delete a record. First example below does it two separate contexts. This requires the state being updated to show EntityState.Deleted. The second method does it in the same method and uses the Remove() call. Note that both the first and second examples have at least 2 round trips to the database. The last example is calling a stored procedure. This is only 1
Working with Related Data
The first example below shows how inserting a new ninja object that has muscles and spunk objects within it. EF will figure out how to add all these objects together, by first inserting the ninja, getting that new ninja�s id and using that to insert the new ninja equipment. This is all done in a single transaction.
Loading related Data
There are two ways to load related data � eager loading and lazy loading
This can be done by using the .Entry() , .Include() or other explicitly calling methods to execute right away an grab all related data with it.
This is loaded on demand, only grabbing the related data at runtime when called. This is done by identifying the related data class as �virtual�. This is not really a good practice and can be dangerous.
Projections are results of a query with targeted properties. For example, in the .Select() statement below it Is getting the Name, DateOfBirth and EqupmentOwned properties only. But the SQL behind the scene shows that EF actually gets all the columns/properties but filters them at the end when returning from the .Select()
Instead of working directly with the database context, it is better practice to use a repository. The repository is an abstract layer between the EF db context and the application�s layer that interacts with this data.
This is used so that EF does not instantiate a class for each of the related records. We use this method to improve performance so that EF doesn�t work extra for this. As example:
Web API IEnumerables
An API that returns an IEnumberable() so that the client can query through the results