We learned default Code-First Conventions in the previous section. Code-First builds conceptual model from your domain classes using default conventions. Code-First leverages a programming pattern referred to as convention over configuration. It means you can override these conventions by configuring your domain classes to provide EF with the information it needs. There are two ways to configure your domain classes.
DataAnnotations
Fluent API
DataAnnotation:
DataAnnotation is a simple attribute based configuration, which you can apply to your domain classes and its properties. You can find most of the attributes in the System.ComponentModel.DataAnnotations namespace. However, DataAnnotation provides only a subset of Fluent API configurations. So, if you don't find some attributes in DataAnnotation, then you have to use Fluent API to configure it.
Following is an example of DataAnnotation used in Student Class:
Fluent API configuration is applied as EF builds the model from your domain classes You can inject the configurations by overriding the DbContext class' OnModelCreating method as following:
publicclassSchoolDBContext: DbContext
{
public SchoolDBContext(): base("SchoolDBConnectionString")
{
}
publicDbSet<Student> Students { get; set; }
publicDbSet<Standard> Standards { get; set; }
publicDbSet<StudentAddress> StudentAddress { get; set; }
protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder){
//Configure domain classes using Fluent API herebase.OnModelCreating(modelBuilder);
}
}
You can use modelBuilder, which is an object of DbModelBuilder class, to configure domain classes.
Let's see DataAnnotation and Fluent API in detail in the next chapter.
We have seen in the Code First Conventions section that it creates database tables for each concrete domain class. However, You can design your domain classes using inheritance. Object-oriented techniques include "has a" and "is a" relationship, whereas SQL-based relational model has only a "has a" relationship between tables. SQL database management systems don't support type inheritance. So, how would you map object-oriented domain classes with the relational database?
Below are three different approaches to represent an inheritance hierarchy in Code-First:
Table per Hierarchy (TPH): This approach suggests one table for the entire class inheritance hierarchy. Table includes discriminator column which distinguishes between inheritance classes. This is a default inheritance mapping strategy in Entity Framework.
Table per Type (TPT): This approach suggests a separate table for each domain class.
Table per Concrete class (TPC): This approach suggests one table for one concrete class, but not for the abstract class. So, if you inherit the abstract class in multiple concrete classes, then the properties of the abstract class will be part of each table of the concrete class.
We are not going into detail here. Visit the following reference link for more detailed information:
We have seen default Code First conventions in the previous section. Learn how to configure domain classes in order to override these conventions in the next section.
We have seen that Code First creates a database automatically in the Simple Code First Example section. Here, we will learn how Code first decides the database name and server while initializing a database.
The following figure shows a database initialization workflow, based on the parameter passed in the base constructor of context class, which is derived from DbContext:
As per the above figure, base constructor of the context class can have the following parameter.
No Parameter
Database Name
Connection String Name
No Parameter:
If you do not specify the parameter in the base constructor of the context class then it creates a database in your local SQLEXPRESS server with a name that matches your {Namespace}.{Context class name}. For example, Code First will create a database named SchoolDataLayer.Context for the following context class:
You can also specify the database name as a parameter in a base constructor of the context class. If you specify a database name parameter, then Code First creates a database with the name you specified in the base constructor in the local SQLEXPRESS database server. For example, Code First will create a database named MySchoolDB for the following context class.
You can also define connection string in app.config or web.config and specify connection string name starting with "name=" in the base constructor of the context class. Consider the following example where we pass name=SchoolDBConnectionString parameter in the base constructor.
In the above context class, we specify a connection string name as a parameter. Please note that connection string name should start with "name=" otherwise, it will consider it as a database name. The database name in the connection string in app.config is SchoolDB-ByConnectionString. Code-First will create a new SchoolDB-ByConnectionString database or use existing SchoolDB-ByConnectionString database at local SQL Server. Make sure that you include providerName = "System.Data.SqlClient" in the connection string.
Thus, Code-First use the base constructor parameter to initialize a database.
We have seen how EF Code-First creates DB tables from domain classes in the previous section. Here, we will learn about default Code-First conventions.
What is Convention?
Convention is a set of default rules to automatically configure a conceptual model based on domain class definitions when working with Code-First. Code-First conventions are defined in System.Data.Entity.ModelConfiguration.Conventions namespace.
Let's see an overview of the various Code-First conventions.
Type Discovery:
In the previous section, we created a context class with DbSet properties for the classes that we want to be part of the model. Code-First will create tables for classes included as DbSet properties, as we have seen the previous section. Code-First also includes any referenced types included in these classes, even if the referenced types are defined in a different assembly.
For example, the following Student entity class includes reference of Teacher class. However, context class does not include Teacher as DbSet property.
So, even if Teacher is not included as an entity set in the context class, Code-First will include it in conceptual model and create a DB table for it, as shown below.
Code-First also includes derived classes even if the context class only includes base class as a DbSet property.
The conventions for the type discovery are:
Code-First includes types defined as a DbSet property in context class.
Code-First includes reference types included in entity types even if they are defined in different assembly.
Code-First includes derived classes even if only the base class is defined as DbSet property.
Primary Key Convention:
In the previous section, we have seen that Code-First automatically creates a Primary Key in each table. The default convention for primary key is that Code-First would create a primary key for a property if the property name is Id or <class name>Id (NOT case sensitive). The data type of a primary key property can be anything, but if the type of the primary key property is numeric or GUID, it will be configured as an identity column.
If you have defined key property other than Id or <ClassName>Id then ModelValidationException will be thrown. For example, consider the following Standard class:
As you can see in the above code, Standard class is defined with StdId key property. Entity Framework will throw the following exception for this.
'System.Data.Entity.ModelConfiguration.ModelValidationException' occurred in EntityFramework.dll EntityType 'Standard' has no key defined. Define the key for this EntityType.
If you want to define StdId as primary key then you have to use DataAnnotations or Fluent API to configure it as primary key. We will see how to do it later in these tutorials.
Relationship Convention:
Code First infer the relationship between the two entities using navigation property. This navigation property can be simple reference type or collection type. For example, we defined Standard navigation property in Student class and ICollection<Student> navigation property in Standard class. So, Code First automatically created one-to-many relationship between Standards and Students DB table by inserting Standard_StandardId foreign key column in the Students table.
The above entities created the following relationship using Standard_StandardId foreign key.
Thus, the default code first convention for relationship automatically inserted a foreign key with <navigation property Name>_<primary key property name of navigation property type> e.g. Standard_StandardId.
Foreign key Convention:
We have seen above that Code First automatically inserts a foreign key when it encounters a navigation property. It is recommended to include a foreign key property on the dependent end of a relationship. Consider the following example:
As you can see in the above code, Student class includes foreign key StandardId, which is the key property in Standard class. Now, Code First will create StandardId column in Students class instead of Standard_StandardId column, as shown below.
Notice that StandardId foreign key is not null in the above figure. This is because int data type is not nullable.
Code First infers the multiplicity of the relationship based on the nullability of the foreign key. If the property is nullable then the relationship is registered as null. Otherwise, the relationship is registered as NOT NULL. Modify data type of StandardId property from int to Nullable<int> in the Student class above to create a nullable foreign key column in the Students table.
Complex type Convention:
Code First creates complex type for the class which does not include key property and also primary key is not registered using DataAnnotation or Fluent API.
Default Code-First Conventions:
The following table lists default code first conventions:
Default Convention For
Description
Table Name
<Entity Class Name> + 's'
EF will create DB table with entity class name suffixed by 's'
Primary key Name
1) Id
2) <Entity Class Name> + "Id" (case insensitive)
EF will create primary key column for the property named Id or <Entity Class Name> + "Id" (case insensitive)
Foreign key property Name
By default EF will look for foreign key property with the same name as principal entity primary key name.
If foreign key property does not exists then EF will create FK column in Db table with <Dependent Navigation Property Name> + "_" + <Principal Entity Primary Key Property Name>
e.g. EF will create Standard_StandardId foreign key column into Students table if Student entity does not contain foreignkey property for Standard where Standard contains StandardId
Null column
EF creates null column for all reference type properties and nullable primitive properties.
Not Null Column
EF creates NotNull columns for PrimaryKey properties and non-nullable value type properties.
DB Columns order
EF will create DB columns same as order of properties in an entity class. However, primary key columns would be moved first.
Properties mapping to DB
By default all properties will map to database. Use [NotMapped] attribute to exclude property or class from DB mapping.
Cascade delete
Enabled By default for all types of relationships.
The following table list C# datatype mapped with SQL datatype and primary key column datatype and length.
C# DataType
Related DB Column DataType
PK Column DataType & Length
int
int
int, Identity column increment by 1
string
nvarchar(Max)
nvarchar(128)
decimal
decimal(18,2)
decimal(18,2)
float
real
real
byte[]
varbinary(Max)
varbinary(128)
datetime
datetime
datetime
bool
bit
bit
byte
tinyint
tinyint
short
smallint
smallint
long
bigint
bigint
double
float
float
char
No mapping
No mapping
sbyte
No mapping
(throws exception)
No mapping
object
No mapping
No mapping
This was an overview of code first conventions. These conventions can be overriden using DataAnnotation or Fluent API. Also, you can define custom conventions for your application using Entity Framework 6.0, onwards.
Let's assume that we want to create a simple application for XYZ School. Users of this School application should be able to add or update Students, Standard (Grade), Teacher, and Course information.
Instead of designing database tables first, let's start creating classes for our school domain, as and when needed. First, we will create two simple Student and Standard classes where every Student is associated with one Standard as shown below.
Now, we are done with the initial domain classes for our school application. Code-First approach also requires context class which should be derived from DbContext as we have created in the basic tutorials section using Database-First approach. Visit DbContext for more information.
Create a context class as shown below, which derives from DBContext class and exposes DbSet properties for the types that you want to be part of the model, e.g. Student and Standard class, in this case. DbSet is a collection of entity classes (aka entity set), so we have given property name as plural of entity name like Students and Standards.
If you run the application, you will be surprised to see that the application runs successfully and one student is successfully inserted into the database.
But, where is the database and what are the tables and its columns?
This is the beauty of Code-First APIs of Entity Framework. It creates the database based on parameter passed in the base constructor of your context class. Since we have not passed any parameter in the constructor of our context class, it created "EF_Code_First_Tutorials.SchoolContext" database in the local SQLEXPRESS database, as shown below. It also created two tables in this database, Students and Standards tables based on Student and Standard domain classes defined above.
As you can see in the above figure, it has created Students and Standards tables and each table contains columns with appropriate datatype and length. The column names and datatype matches with the properties of the respective domain classes. It has also made StudentId and StandardId as PK (primary key) and Standard_StandardId column as FK (foreign key).
This way, without creating a database first, you can start writing an application that will eventually create the database from your domain classes.
You must be wondering how it has created columns with appropriate datatypes and lengh with PK & FK, right? The answer is, using code-first conventions.
Let's setup the development environment for Code-First before starting on it.
Install the following tools to work with Entity Framework Code-First:
.NET Framework 4.5
Visual Studio 2012
MS SQL Server 2008/2012 Express
Install EF via Nuget:
Here, we will install Entity Framework API (EntityFramework.dll) via NuGet in the VS 2012 console application. (You can install EF via NuGet the same way in any version of Visual Studio.)
First, create the console application. Right click on your project in the solution explorer and select Manage NuGet Packages..
This will open Manage NuGet Packages dialogue box. Now, select Online in the left bar and search for EntityFramework as shown below.
This will search for all the packages related to Entity Framework. Select EntityFramework and click on Install.
Click on the I Accept button in the License Acceptance dialogue box to start the installation.
After installation, make sure that the appropriate version of EntityFramework.dll is included in the project.
Now, we are ready to use Entity Framework Code-First in our sample console project. Let's start writing our first simple code-first example in the next section.