If you haven't read it yet, check out part 1 in my Entity Framework series.
In my previous blog post I demonstrated a handful of methods to optimize query performance when using Entity Framework. While having a few tricks up your sleeve to help write efficient queries is a good thing, an astute developer will also want to make sure the schema is generated reasonably by EF Code First. Some of Code First’s defaults are very well thought out, while others are terrible and you’ll definitely want to override. I’ll show you two different methods of taking control of the database schema generation.
First, let’s look at the schema that’s generated by the example project we used in the previous post using default conventions (click on the image to view the code on Github):
Here are some items that a picky developer might want to override:
- Removing pluralization of the table names
- Overriding FK columns name so they are more self-explanatory
- Providing a more reasonable string length than nvarchar(max) (here’s an explanation on why we don’t want to use nvarchar(max) for all of our string columns)
- Explicitly specifying null/not null columns
- Cascading delete on child objects
We have two ways to override default contentions: Data Annotations and custom configuration classes. While Data Annotations might be the easiest and quickest way, I generally use custom configuration classes because it gives us better Separation of Concerns
. I do not like my domain models being littered with Data Annotations because it’s distracting and would quickly become difficult to manage if we changed our data persistence plans.
Customizing Using Custom Configuration Classes
Follow along with my sample code on Github
Wiring up custom configuration classes consists of two steps: creating the actual configuration class with your customizations and letting Entity Framework know to use it. I’ve seen a few methods to accomplish this, but I generally prefer making a configuration class per type and then overriding the OnModelCreating method in your Context class. Here’s how you can achieve this (in this sample, all of my configuration classes are inline—if you check the code here on GitHub
, you’ll see it split apart):
And here’s the updated schema (much better!):
Customizing Using Data Annotations
Most of the Data Annotations that I’ve used live in the System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema namespaces. Here’s
how I achieved the same schema above using Data Annotations (this was a great reminder of why I don’t like Data Annotations):
Stay tuned for the next post where I explain Entity Framework Migrations, which is a powerful tool for helping achieve Continuous Integration. I’ll show how you can quickly set this up using automatic migrations, and how we can achieve database versioning using advanced migrations. I’ll show you how you can wire EF Migrations into your Continuous Integration tools. EF Migrations is by far my favorite feature of Entity Framework, so make sure you don’t miss this one.
Continue to part 3: Migrations.