CHAPTER 2
Domain Model
Scenario
Let’s consider the following scenario as the basis for our study.
- The domain model
You will find all these classes in the accompanying source code. Let’s try to make some sense out of them:
- A Customer has a number of Projects.
- Each Project has a collection of ProjectResources, belongs to a single Customer, and has a ProjectDetail with additional information.
- A ProjectDetail refers to a single Project.
- A ProjectResource always points to an existing Resource and is assigned to a Project with a given Role.
- A Resource knows some Technologies and can be involved in several Projects.
- A Technology can be collectively shared by several Resources.
- Both Customers and Resources have Contact information.
Note: You can find the full source code in the following Git repository: https://bitbucket.org/syncfusiontech/entity-framework-code-first-succinctly/overview.
Core Concepts
Before a class model can be used to query a database or to insert values into it, Entity Framework needs to know how it should translate code (classes, properties, and instances) back and forth into the database (specifically, tables, columns and records). For that, it uses a mapping, for which two APIs exist. More on this later, but first, some fundamental concepts.
Contexts
A context is a class that inherits from DbContext and which exposes a number of entity collections in the form of DbSet<T> properties. Nothing prevents you from exposing all entity types, but normally you only expose aggregate roots, because these are the ones that make sense querying on their own.
An example context might be the following.
public class ProjectsContext : DbContext { public DbSet<Tool> Tools { get; set; } public DbSet<Resource> Resources { get; set; } public DbSet<Project> Projects { get; set; } public DbSet<Customer> Customers { get; set; } public DbSet<Technology> Technologies { get; set; } } |
Tip: Do notice that both setters and getters for the entity collections are public.
Note: Feel free to add your own methods, business or others, to the context class.
The DbContext class offers a number of constructors, mostly for configuring the connection string:
- If the no-arguments constructor is called, the DbContext will assume that a connection string with the same name as the context’s class will exist in the configuration file.
- There’s also a constructor that takes a single string parameter. This parameter will either be a full connection string that is specific to the current database provider or a name of a connection string that must be present in the configuration file.
- For the sake of completeness, another constructor exists that takes an existing DbConnection; Entity Framework might not take full control of this connection, for example, it won’t try to dispose of it when no longer needed.
public class ProjectsContext : DbContext { public ProjectsContext() { } public ProjectsContext(String nameOrConnectionString): base(nameOrConnectionString) { } public ProjectsContext(DbConnection existingConnection, Boolean contextOwnsConnection): base(existingConnection, contextOwnsConnection) { } } |
If we use the constructor overload that takes a connection string by its name, we must use the format “Name=Some Name”.
public class ProjectsContext : DbContext { public ProjectsContext(String name) : base("Name=AnotherName") { } } |
Entities
At the very heart of the mapping is the concept of entity. An entity is just a class that is mapped to an Entity Framework context and which has an identity, or a property that uniquely identifies instances of it. In DDD parlance, it is said to be an aggregate root if it is meant to be directly queried, think of a Project or a Customer, or an entity if it is loaded together with an aggregate root and not generally considerable on its own, such as project details or customer address. An entity is persisted on its own table and may have any number of business or validation methods.
public class Project { public Project() { this.ProjectResources = new HashSet<ProjectResource>(); }
public Int32 ProjectId { get; set; }
public String Name { get; set; }
public DateTime Start { get; set; }
public DateTime? End { get; set; }
public virtual ProjectDetail Detail { get; set; }
public virtual Customer Customer { get; set; } public void AddResource(Resource resource, Role role) { resource.ProjectResources.Add(new ProjectResource() { Project = this, Resource = resource, Role = role }); }
public Resource ProjectManager { get { return (this.ProjectResources.ToList() .Where(x => x.Role == Role.ProjectManager) .Select(x => x.Resource).SingleOrDefault()); } }
public IEnumerable<Resource> Developers { get { return (this.ProjectResources.Where(x => x.Role == Role.Developer) .Select(x => x.Resource).ToList()); } }
public IEnumerable<Resource> Testers { get { return (this.ProjectResources.Where(x => x.Role == Role.Tester) .Select(x => x.Resource)).ToList(); } }
public virtual ICollection<ProjectResource> ProjectResources { get; protected set; }
public override String ToString() { return (this.Name); } } |
Here you can see some patterns that we will be using throughout the book:
- An entity needs to have at least a public parameter-less constructor.
- An entity always has an identifier property, which has the same name and ends with Id.
- Collections are always generic, have protected setters, and are given a value in the constructor in the form of an actual collection (like HashSet<T>).
- Calculated properties are used to expose filtered sets of actually persisted properties.
- Business methods are used for enforcing business rules.
- A textual representation of the entity is supplied by overriding ToString.
A domain model where its entities have only properties (data) and no methods (behavior) is sometimes called an anemic domain model. You can find a good description for this anti-pattern on Martin Fowler’s web site: http://www.martinfowler.com/bliki/AnemicDomainModel.html.
Complex Types
A complex type is also a class with some properties and maybe methods, but unlike an entity, it doesn’t have an identity property and doesn’t have its own table for persistence. Instead, its properties are saved into the same table as its declaring type. A complex type is useful for grouping properties that conceptually should always appear together, such as the city, country, street, and zip code in an address. By reusing complex types, we can have the same logic repeated in different entities. Both a customer and a human resource might have contact information with the same structure:
public class ContactInformation { public String Email { get; set; }
public String Phone { get; set; } } public class Resource { public ContactInformation Contact { get; set; } } public class Customer { public ContactInformation Contact { get; set; } } |
Complex types have the following limitations:
- They cannot have navigation properties (references or collections, see next topics).
- They cannot be null, or their containing entity must initialize them.
- They cannot point to their containing entity.
Scalar Properties
Scalars are simple values, like strings, dates, and numbers. They are where actual entity data is stored, and can be of one of any of these types.
Table 1: Scalar Properties
.NET Type | SQL Server Type | Description |
|---|---|---|
Boolean | Single bit. | |
Byte | Single byte (8 bits). | |
Char | CHAR, | ASCII or UNICODE char (8 or 16 bits). |
Int16 | Short integer (16 bits). | |
fInt32 | Integer (32 bits). | |
Int64 | Long (64 bits). | |
Single | Floating point number (32 bits). | |
Double | Double precision floating point number (64 bits). | |
Decimal | SMALLMONEY | Currency (64 bits) or small currency (32 bits). |
Guid | Globally Unique Identifier (GUID). | |
DateTime | DATE, | Date with or without time. |
DateTimeOffset | Date and time with timezone information. | |
TimeSpan | Time. | |
String | ASCII (8 bits per character), UNICODE (16 bits) or XML character string. Can also represent a Character Long Object (CLOB). | |
Byte[] | VARBINARY , | Binary Large Object (BLOB). |
Enum | Enumerated value. | |
DbGeography | Geography spatial type. | |
DbGeometry | Planar spatial type. |
The types Byte, Char, and String can have a maximum length specified. A value of -1 translates to MAX.
All scalar types can be made nullable, meaning they might have no value set. In the database, this is represented by a NULL column.
Scalar properties need to have both a getter and a setter, but the setter can have a more restricted visibility than the getter: internal, protected internal or protected.
Some examples of scalar properties are as follows.
public class Project { public Int32 ProjectId { get; set; }
public String Name { get; set; } public DateTime Start { get; set; }
public DateTime? End { get; set; } } |
Identity Properties
One or more of the scalar properties of your entity must represent the underlying table’s primary key, which can be single or composite.
Primary key properties can only be of any of the basic types, which is any type in the list above except arrays and enumerations, but no complex types or other entity’s types.
References
A reference from an entity to another defines a bidirectional relation. There are two types of reference relations:
- Many-to-one: several instances of an entity can be associated with the same instance of another type (such as projects that are owned by a customer).

- Many-to-one relationship
- One-to-one: an instance of an entity is associated with another instance of another entity; this other instance is only associated with the first one (such as a project and its detail).

- One-to-one relationship
In EFCF, we represent an association by using a property of the other entity’s type.

- References: one-to-one, many-to-one
We call an entity’s property that refers to another entity as an endpoint of the relation between the two entities.
public class Project { //one endpoint of a many-to-one relation public virtual Customer Customer { get; set; } //one endpoint of a one-to-one relation public virtual ProjectDetail Detail { get; set; } } public class ProjectDetail { //the other endpoint of a one-to-one relation public Project Project { get; set; } } public class Customer { //the other endpoint of a many-to-one relation public virtual ICollection<Project> Projects { get; protected set; } } |
Note: By merely looking at one endpoint, we cannot immediately tell what its type is (one-to-one or many-to-one), we need to look at both endpoints.
Collections
Collections of entities represent one of two possible types of bidirectional relations:
- One-to-many: a single instance of an entity is related to multiple instances of some other entity’s type (such as a project and its resources).

- One-to-many relationship
- Many-to-many: possibly a number of instances of a type can be related with any number of instances of another type (such as resources and the technologies they know).

- Many-to-many relationship

- Collections: one-to-many, many-to-many
Entity Framework only supports declaring collections as ICollection<T> (or some derived class or interface) properties. In the entity, we should always initialize the collections properties in the constructor.
public class Project { public Project() { this.ProjectResources = new HashSet<ProjectResource>(); } public virtual ICollection<ProjectResource> ProjectResources { get; protected set; } } |
Note: References and collections are collectively known as navigation properties, as opposed to scalar properties.
Mapping by Attributes
Overview
Probably the most used way to express our mapping intent is to apply attributes to properties and classes. This has the advantage that, by merely looking at a class, one can immediately infer its database structure.
Schema
Unless explicitly set, the table where an entity type is to be stored is determined by a convention (more on this later on), but it is possible to set the type explicitly by applying a TableAttribute to the entity’s class.
[Table("MY_SILLY_TABLE", Schema = "dbo")] public class MySillyType { } |
The Schema property is optional and should be used to specify a schema name other than the default. A schema is a collection of database objects (tables, views, stored procedures, functions, etc.) in the same database. In SQL Server, the default schema is dbo.
For controlling how a property is stored (column name, physical order, and database type), we apply a ColumnAttribute.
[Column(Order = 2, TypeName = "VARCHAR")] public String Surname { get; set; } [Column(Name = "FIRST_NAME", Order = 1, TypeName = "VARCHAR")] public String FirstName { get; set; } |
If the TypeName is not specified, Entity Framework will use the engine’s default for the property type. SQL Server will use NVARCHAR for String properties, INT for Int32, BIT for Boolean, etc. We can use it for overriding this default.
The Order applies a physical order to the generated columns that might be different from the order by which properties appear on the class. When the Order property is used, there should be no two properties with the same value in the same class.
Marking a scalar property as required requires the usage of the RequiredAttribute.
[Required] public String Name { get; set; } |
Tip: When this attribute is applied to a String property, it not only prevents the property from being null, but also from taking an empty string.
Tip: For value types, the actual property type should be chosen appropriately. If the column is non-nullable, one should not choose a property type that is nullable, such as Int32?.
For a required associated entity, it is exactly the same.
[Required] public Customer Customer { get; set; } |
Setting the maximum allowed length of a string column is achieved by means of the MaxLengthAttribute.
[MaxLength(50)] public String Name { get; set; } |
The MaxLengthAttribute can be also used to set a column as being a CLOB, a column containing a large amount of text. SQL Server uses the types NVARCHAR(MAX) and VARCHAR(MAX). For that, we pass a length of -1.
[MaxLength(-1)] public String LargeText { get; set; } |
It can also be used to set the size of a BLOB (in SQL Server, VARBINARY) column.
[MaxLength(-1)] public Byte[] Picture { get; set; } |
Like in the previous example, the -1 size will effectively be translated to MAX.
Ignoring a property, having Entity Framework never consider it for any operations, is as easy as setting a NotMappedAttribute on the property.
[NotMapped] public String MySillyProperty { get; set; } |
Fully ignoring a type, including any properties that might refer to it, is also possible by applying the NotMappedAttribute to its class instead.
[NotMapped] public class MySillyType { } |
Primary Keys
While database tables strictly don’t require a primary key, Entity Framework requires it. Both single column as well as multi-column (composite) primary keys are supported. Marking a property, or properties, as the primary key is achieved by applying a KeyAttribute.
[Key] public Int32 ProductId { get; set; } |
If we have a composite primary key, we need to apply a ColumnAttribute as well. In it we need to give an explicit order by means of the Order property so that EF knows when an entity is loaded by the Find method, which argument refers to which property.
[Key] [Column(Order = 1)] public Int32 ColumnAId { get; set; } [Key] [Column(Order = 2)] public Int32 ColumnBId { get; set; } |
Primary keys can also be decorated with an attribute that tells Entity Framework how keys are to be generated (by the database or manually). This attribute is DatabaseGeneratedAttribute, and its values are explained in further detail in the section Identifier Strategies.
Navigation Properties
We typically don’t need to include foreign keys in our entities; instead, we use references to the other entity, but we can have them as well. That’s what the ForeignKeyAttribute is for.
public virtual Customer Customer { get; set; } [ForeignKey("Customer")] public Int32 CustomerId { get; set; } |
The argument to ForeignKeyAttribute is the name of the navigation property that the foreign key relates to.
Now suppose we have several relations from an entity to the other. For example, a customer might have two collections of projects: one for the current and other for the past projects. It could be represented in code as this.
public partial class Customer { //the other endpoint will be the CurrentCustomer [InverseProperty("CurrentCustomer")] public virtual ICollection<Project> CurrentProjects { get; protected set; } //the other endpoint will be the PastCustomer [InverseProperty("PastCustomer")] public virtual ICollection<Project> PastProjects { get; protected set; } } public partial class Project { public virtual Customer CurrentCustomer { get; set; } public virtual Customer PastCustomer { get; set; } } |
In that case, it is impossible for EF to figure out which property should be the endpoint for each of these collections, hence the need for the InversePropertyAttribute. When applied to a collection navigation property, it tells Entity Framework what is the name of the other endpoint’s reference property that will point back to it.
Note: When configuring relationships, you only need to configure one endpoint.
Computed Columns
Entity Framework Code First does not support generating computed columns—columns whose values are not physically stored in a table but instead come from SQL formulas—automatically, but you can do it manually and have them mapped to your entities. A typical case is combining a first and a last name into a full name, which can be achieved on SQL Server very easily.
- Computed columns
Another example of a column that is generated on the database is when we use a trigger for generating its values. You can map server-generated columns to an entity, but you must tell Entity Framework that this property is never to be inserted. For that we use the DatabaseGeneratedAttribute with the option DatabaseGeneratedOption.Computed.
public virtual String FirstName { get; set; }
public virtual String LastName { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public virtual String FullName { get; protected set; } |
Since the property will never be set, we can have the setter as a protected method, and we mark it as DatabaseGeneratedOption.Computed to let Entity Framework know that it should never try to INSERT or UPDATE this column.
With this approach, you can query the FullName computed property with both LINQ to Objects as well as LINQ to Entities.
//this is executed by the database var me = ctx.Resources.SingleOrDefault(x => x.FullName == "Ricardo Peres"); //this is executed by the process var me = ctx.Resources.ToList().SingleOrDefault(x => x.FullName == "Ricardo Peres"); |
Complex Types
Complex types should be decorated with the ComplexTypeAttribute as in the following.
[ComplexType] public class ContactInformation { public String Email { get; set; }
public String Phone { get; set; } } |
External Metadata
If you have a situation where you can’t change an entity’s code, the entity could have been generated automatically from a tool. See Generating Code Automatically for some examples of this. There’s still something that you can do, provided the entities are generated as partial classes. The MetadataTypeAttribute allows us to have a class that contains the metadata—including, in this case, mapping attributes—for another class. Here’s a quick example.
//the original Project class public partial class Project { //the following attributes will come from the ProjectMetadata class /*[Required] [MaxLength(50)]*/ public String Name { get; set; } } //the new declaration [MetadataType(typeof(ProjectMetadata))] public partial class Project { sealed class ProjectMetadata { [Required] [MaxLength(50)] public String Name { get; set; } } } |
This second class declaration is created in a new file and must reside in the same namespace as the original one. We don’t need—in fact, we can’t—to add any of its properties or methods; it will just serve as a placeholder for the MetadataTypeAttribute declaration. In the inner class ProjectMetadata, we will declare any properties for which we want to apply attributes.
Note: This is a good workaround for when code is generated automatically, provided all classes are generated as partial.
Limitations
As of the current version of EFCF, there are some mapping concepts that cannot be achieved with attributes:
- Configuring cascading (see Cascading Deletes).
- Applying the Concrete Table Inheritance pattern (see Inheritance Strategies).
For these, we need to resort to code configuration, which is explained next.
Mapping by Code
Overview
Convenient as attribute mapping may be, it has some drawbacks:
- We need to add references in our domain model to the namespaces and assemblies where the attributes are defined (such as “domain pollution”).
- We cannot change things dynamically; attributes are statically defined and cannot be overwritten.
- There isn’t a centralized location where we can enforce our own conventions.
To help with these limitations, Entity Framework Code First offers an additional mapping API: code or fluent mapping. All functionality of the attribute-based mapping is present and more. Let’s see how we implement the most common scenarios.
Fluent, or code, mapping is configured on an instance of DbModelBuilder and normally the place where we can access one is in the OnModelCreating method of the DbContext.
public class ProjectsContext : DbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { //configuration goes here base.OnModelCreating(modelBuilder); } } |
This infrastructure method is called by Entity Framework when it is initializing a context, after it has automatically mapped whatever entity classes are referenced as DbSet<T> collections or referenced through them.
Schema
Here’s how to configure the entity mappings by code.
//set the table and schema modelBuilder.Entity<Project>().ToTable("project", "dbo"); //ignoring an entity and all properties of its type modelBuilder.Ignore<Project>(); |
This is an example of mapping individual properties. Notice how the API allows chaining multiple calls together by, in this case, setting simultaneously the column name, type, maximum length, and required flag. This is very useful and renders the code in a more readable way.
//ignore a property modelBuilder.Entity<Project>().Ignore(x => x.SomeProperty); //set a property’s values (column name, type, length, nullability) modelBuilder.Entity<Project>().Property(x => x.Name).HasColumnName("NAME") .HasColumnType("VARCHAR").HasMaxLength(50).IsRequired(); |
Primary Keys
The primary key and the associated generation strategy are as follows.
//setting a property as the key modelBuilder.Entity<Project>().HasKey(x => x.ProjectId); //and the generation strategy modelBuilder.Entity<Project>().Property(x => x.ProjectId) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); //composite keys modelBuilder.Entity<CompositeEntity>().HasKey(x => new { x.KeyColumnAId, x.KeyColumnBId }); |
Navigation Properties
Navigation properties (references and collections) are as follows.
//a bidirectional many-to-one and its inverse with cascade modelBuilder.Entity<Project>().HasRequired(x => x.Customer).WithMany(x => x.Projects).WillCascadeOnDelete(true); //a bidirectional one-to-many modelBuilder.Entity<Customer>().HasMany(x => x.Projects) .WithRequired(x => x.Customer); //a bidirectional many-to-many modelBuilder.Entity<Technology>().HasMany(x => x.Resources) .WithMany(x => x.Technologies); //a bidirectional one-to-one-or-zero with cascade modelBuilder.Entity<Project>().HasOptional(x => x.Detail) .WithRequired(x => x.Project).WillCascadeOnDelete(true); //a bidirectional one-to-one (both sides required) with cascade modelBuilder.Entity<Project>().HasRequired(x => x.Detail) .WithRequiredPrincipal(x => x.Project).WillCascadeOnDelete(true); //a bidirectional one-to-many with a foreign key property (CustomerId) modelBuilder.Entity<Project>().HasRequired(x => x.Customer).WithMany(x => x.Projects) .HasForeignKey(x => x.CustomerId); //a bidirectional one-to-many with a non-conventional foreign key column modelBuilder.Entity<Project>().HasRequired(x => x.Customer).WithMany(x => x.Projects) .Map(x => x.MapKey("FK_Customer_Id")); |
Note: When configuring relationships, you only need to configure one endpoint.
Computed Columns
A simple column that is generated at the database by a formula, instead of being physically stored, can be done with the following.
modelBuilder.Entity<Resource>().Property(x => x.FullName) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); |
Complex Types
Declaring a class as a complex type, no need to do it for individual properties, can be done with the following.
modelBuilder.ComplexType<ContactInformation>(); //a property in a complex type modelBuilder.ComplexType<ContactInformation>().Property(x => x.Email).IsRequired() .HasMaxLength(50); |
As you can imagine, if we use fluent mapping extensively, the OnModelCreating method can get quite complex. Realizing this, EFCF offers the possibility to group entity configurations in their own class; this class must derive from EntityTypeConfiguration<T>, and here is an example of it.
modelBuilder.Configurations.Add(new CustomerConfiguration()); public class CustomerConfiguration : EntityTypeConfiguration<Customer> { public CustomerConfiguration() { this.Table("FK_Customer_Id", "dbo"); this.Property(x => x.Name).HasMaxLength(50).IsRequired(); } } |
Note: You are free to mix mappings in the OnModelCreating method and in configuration classes, but you should follow a consistent approach.
Identifier Strategies
Overview
Entity Framework requires that all entities have an identifier property that will map to the table’s primary key. If this primary key is composite, multiple properties can be collectively designated as the identifier.
Identity
Although Entity Framework is not tied to any specific database engine, it is certainly true that out of the box it works better with SQL Server. Specifically, it knows how to work with IDENTITY columns, arguably the most common way in the SQL Server world to generate primary keys. Until recently, it was not supported by some major database engines such as Oracle.
By convention, whenever Entity Framework encounters a primary key of an integer type (Int32 or Int64), it will assume that it is an IDENTITY column. When generating the database, it will start with value 1 and use the increase step of 1 as well. It is not possible to change these parameters.
Tip: Although similar concepts exist in other database engines, Entity Framework can only use IDENTITY with SQL Server.
Manual
In the event that the identifier value is not automatically generated by the database, it must be manually set for each entity to be saved. If it is Int32 or Int64, and you want to use attributes for the mapping, then mark the identifier property with a DatabaseGeneratedAttribute and pass it the DatabaseGeneratedOption.None. This will avoid the built-in convention that will assume IDENTITY.
[Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public Int32 ProjectId { get; set; } |
Use the following if you prefer fluent mapping.
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Project>().HasKey(x => x.ProjectId).Property(x => x.ProjectId) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
base.OnModelCreating(modelBuilder); } |
In this case, it is your responsibility to assign a valid identifier that doesn’t already exist in the database. This is quite complex, mostly because of concurrent accesses and transactions; a popular alternative consists of using a Guid for the primary key column. You still have to initialize its value yourself, but the generation algorithm assures that there won’t ever be two identical values.
public Project() { //always set the id for every new instance of a Project this.ProjectId = Guid.NewGuid(); } [Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public Guid ProjectId { get; set; } |
Note: When using non-integral identifier properties, the default is to not have them generated by the database, so you can safely skip the DatabaseGeneratedAttribute.
Note: Using Guids for primary keys also has the benefit that you can merge records from different databases into the same table; the records will never have conflicting keys.
Inheritance Strategies
Consider the following class hierarchy.

- An inheritance model
In this example, we have an abstract concept, a Tool, and three concrete representations of it: a DevelopmentTool, a TestingTool, and a ManagementTool. Each Tool must be one of these types.
In object-oriented languages, we have class inheritance, which is something relational databases don’t have. How can we store this in a relational database?
Martin Fowler, in his seminal work Patterns of Enterprise Application Architecture, described three patterns for persisting class hierarchies in relational databases:
- Single Table Inheritance or Table Per Class Hierarchy: a single table is used to represent the entire hierarchy; it contains columns for all mapped properties of all classes. Many of these will be NULL because they will only exist for one particular class; one discriminating column will store a value that will tell Entity Framework what class a particular record will map to.

- Single Table Inheritance data model
- Class Table Inheritance or Table Per Class: a table will be used for the columns for all mapped base class properties, and additional tables will exist for all concrete classes; the additional tables will be linked by foreign keys to the base table.

- Class Table Inheritance data model
- Concrete Table Inheritance or Table Per Concrete Class: one table for each concrete class, each with columns for all mapped properties, either specific or inherited by each class.

- Concrete Table Inheritance data model
You can see a more detailed explanation of these patterns on Martin’s web site at http://martinfowler.com/eaaCatalog/index.html. For now, I’ll leave you with some thoughts:
- Single Table Inheritance, when it comes to querying from a base class, offers the fastest performance, because all information is contained in a single table. However, if you have lots of properties in all of the classes, it will be a difficult read, and you will have many nullable columns. In all of the concrete classes, all properties must be optional because they must allow null values. This is because different entities will be stored in the same class and not all share the same columns.
- Class Table Inheritance offers a good balance between table tidiness and performance. When querying a base class, a LEFT JOIN will be required to join each table from derived classes to the base class table. A record will exist in the base class table and in exactly one of the derived class tables.
- Concrete Table Inheritance for a query for a base class requires several UNIONs, one for each table of each derived class, because Entity Framework does not know beforehand in which table to look. This has the consequence that you cannot use IDENTITY as the identifier generation pattern or anyone that might generate identical values for any two tables. Entity Framework would be confused if it found two records with the same ID. Also, you will have the same columns, those from the base class, duplicated on all tables.
As for what Entity Framework is concerned, there really isn’t any difference; classes are naturally polymorphic. See Chapter 4, “Getting Data from the Database,” for learning how we can perform queries on class hierarchies.
Here’s how we can apply each of these patterns. First, here is an example for Single Table Inheritance.
public abstract class Tool { public String Name { get; set; }
public Int32 ToolId { get; set; } } public class DevelopmentTool : Tool { //String is inherently nullable public String Language { get; set; } } public class ManagementTool : Tool { //nullable Boolean public Boolean ? CompatibleWithProject { get; set; } } public class TestingTool : Tool { //nullable Boolean public Boolean ? Automated { get; set; } } |
As you can see, there’s nothing special you need to do. This is the default inheritance strategy. One important thing, though: because all properties of each derived class will be stored in the same table, all of them need to be nullable. It’s easy to understand why. Each record in the table will potentially correspond to any of the derived classes, and their specific properties only have meaning to them, not to the others, so they may be undefined (NULL). In this example, I have declared all properties in the derived classes as nullables.
Let’s move on to the next pattern, Class Table Inheritance.
public abstract class Tool { public String Name { get; set; }
public Int32 ToolId { get; set; } } [Table("DevelopmentTool")] public class DevelopmentTool : Tool { public String Language { get; set; } } [Table("ManagementTool")] public class ManagementTool : Tool { public Boolean CompatibleWithProject { get; set; } } [Table("TestingTool")] public class TestingTool : Tool { public Boolean Automated { get; set; } } |
Here, the difference is that we specify a table name for all of the derived entities. There is no need to do it for the base class, we’ll just use the default. Properties of derived classes can be non-nullable, because they are stored in their own tables.
Finally, the Concrete Table Inheritance requires some more work.
public abstract class Tool { protected Tool() { //create a unique id for each instance this.ToolId = Guid.NewGuid(); } public String Name { get; set; }
//Guid instead of Int32 public Guid ToolId { get; set; } } [Table("DevelopmentTool")] public class DevelopmentTool : Tool { public String Language { get; set; } } [Table("ManagementTool")] public class ManagementTool : Tool { public Boolean CompatibleWithProject { get; set; } } [Table("TestingTool")] public class TestingTool : Tool { public Boolean Automated { get; set; } } public class ProjectsContext : DbContext { protected override void OnModelCreating(DbModelBuilder modelBuilder) { //map the inherited properties for each derived class modelBuilder.Entity<ManagementTool>().Map(m => m.MapInheritedProperties()); modelBuilder.Entity<TestingTool>().Map(m => m.MapInheritedProperties()); modelBuilder.Entity<DevelopmentTool>().Map(m => m.MapInheritedProperties());
base.OnModelCreating(modelBuilder); } } |
Some notes:
- We cannot use the default, conventional, IDENTITY generation pattern for the primary key, because each table will have its own IDENTITY, and thus there would be records with the same primary key in each derived entity table. If we were going to query from the base class, for example, ctx.Tools.Find(1), which record would EF choose? I chose to use a Guid as the primary key, which is a common decision, hence the constructor.
- We need to override the OnModelCreating method to complete the mapping.
Conventions
The current version of Entity Framework Code First at the time this book was written (5.0) comes along with a number of conventions. Conventions dictate how EFCF will configure some aspects of your model when they are not explicitly defined.
The full list of included conventions is comprised of the classes implementing IConvention that live in the System.Data.Entity.ModelConfiguration.Conventions namespace of the EntityFramework assembly. You can generally tell what they are supposed to do by looking at each class’ description.
The most usual conventions are:
- EF will look for a connection string with the same name as the context (built in).
- All types exposed from a DbSet<T> collection in the DbContext-derived class with public setters and getters are mapped automatically (built in).
- All properties of all mapped types with a getter and a setter (any visibility) are mapped automatically, unless explicitly excluded (built in).
- All properties of nullable types are not required; those from non-nullable types (value types in .NET) are required.
- All virtual properties (references and collections) should be lazy loaded (built in).
- Single primary keys of integer types will use IDENTITY as the generation strategy (built in).
- If an entity is named with a singular noun, its corresponding table will have a pluralized name (PluralizingTableNameConvention).
- Primary key properties not explicitly set will be found automatically (IdKeyDiscoveryConvention).
- Associations to other entities are discovered automatically and the foreign key columns are built by composing the foreign entity name and its primary key (AssociationInverseDiscoveryConvention, NavigationPropertyNameForeignKeyDiscoveryConvention, PrimaryKeyNameForeignKeyDiscoveryConvention and TypeNameForeignKeyDiscoveryConvention).
- Child entities are deleted from the database whenever their parent is, if the relation is set to required (OneToManyCascadeDeleteConvention and ManyToManyCascadeDeleteConvention).
For now, there is no way to add our own custom conventions. If we want to disable a convention, just remove its class from the DbModelBuilder instance in the OnModelCreating override.
protected override void OnModelCreating(DbModelBuilder modelBuilder) { //create tables with the same names as the entities, do not pluralize them modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); base.OnModelCreating(modelBuilder); } |
We have already seen how to override the conventional table and column names.
//change the physical table name [Table("MY_PROJECT")] public class Project { //change the physical column name [Column("ID")] public Int32 ProjectId { get; set; } } |
For the connection string to use, EF lets us call a base constructor that receives a connection string.
public class ProjectsContext : DbContext { //use a different connection string public ProjectsContext(): base("Name=SomeConnectionString") { } } |
Note: The next version of Entity Framework, 6.0, will support custom conventions.
Obtaining the Model Definition
If you need to import the model you generated using Code First to “classical” Entity Framework, it’s just a matter of exporting an EDMX file and importing it on another project.
var ctx = new ProjectsContext(); XmlWriterSettings settings = new XmlWriterSettings { Indent = true };
using (XmlWriter writer = XmlWriter.Create("ProjectsContext.edmx", settings)) { EdmxWriter.WriteEdmx(ctx, writer); } |
If you open the produced file with Visual Studio, this is what you get.

- : The Entity Data Model definition (EDMX)
This is a perfectly valid Entity Data Model definition, and you can import it into a project that uses “classic” Entity Framework and generate a class model from it.
Generating Code Automatically
One thing that is often requested is the ability to generate entity types that Entity Framework Code First can use straight away. This normally occurs when we have a large database with a big number of tables for which it would be hard to call classes manually. This is not exactly the purpose of Code First, but we have some options.
The first option is to start with “classic” Entity Framework. First, we add an item of type ADO.NET Entity Data Model.

- Add an Entity Data Model
We will want to generate entities from an existing database.

- : Generate model from database
Next, we have to create or select an existing connection string.

- Set the connection string for generating the entities from the database
And choose the database objects (tables, views, stored procedures) that we want to map.

- Choose the database objects to map
Finally, the model is generated.

- The generated Entity Data Model
Tip: Inheritance is lost because EF has no way to know how we would want to have it.
As it is now, it won’t produce a Code First context and entities, but instead regular “classic” Entity Framework context and entities. In order to do the trick, we need to add a code generation item, which we can do by right-clicking the design surface and selecting that option.

- Adding a DbContext generator
We then select the EF 5.x DbContext Generator item, and that’s it. As soon as you build your project, you will have both the context and the entities. Keep one thing in mind: the changes you make to the code will be lost if you update the model or have it regenerate the code!
Your other option is to use the Entity Framework Power Tools. This extension can be obtained from the Extension Manager of Visual Studio; at the time this book was written (August-September 2013), it is still in beta.

- : Entity Framework Power Tools extension
This extension adds a context menu to Visual Studio projects named Entity Framework. Inside of it there’s a Reverse Engineer Code First option.

- : Reverse engineering a Code First model
As soon as you accept the connection string properties, Visual Studio will go to the database and will generate a context, its entities and associations for all the tables in the selected database, as well as its fluent mappings.

Figure 22: The generated Code First model
As you can see, this is way faster than with the “classic” approach. Some remarks on the process:
- This is a one-off generation: you cannot refresh the generated entities from the database, just replace them entirely, which means you will lose any changes you made to the code.
- The tool will generate mappings for all tables, there is no option to select just some of them.
- Inheritances are lost, which is understandable because they don’t exist at the database level, only at the class level.
Tip: The Power Tools extension is still in beta, so you can expect some bugs to exist
- 1800+ high-performance UI components.
- Includes popular controls such as Grid, Chart, Scheduler, and more.
- 24x5 unlimited support by developers.