In-Depth

Not Just a Designer: Code First in Entity Framework

Code First is a new development approach in the Entity Framework stack that can simplify the understanding and maintenance of your domain model.

In the middle of 2008, Microsoft published the first version of the Entity Framework (Entity Framework 1) as part of Visual Studio 2008 SP1. The Entity Framework was created as an object-relational mapping (OR/M) tool that helps create an abstraction layer on top of ADO.NET namespaces. When it first shipped, the Entity Framework supplied two development approaches out of the box: the Database First approach and the Model First approach.

In the Database First approach, you started with an existing database and used the Entity Framework wizard to create the Entity Data Model (EDM). The model was built as a one-to-one mapping between the database and the conceptual model, and after it was created you could customize it to make it more like the domain requirements.

On the other hand, the Model First approach was limited in the first version. When Visual Studio 2010 and the Microsoft .NET Framework 4 were shipped, the Model First implementation was improved significantly. In Model First, you could start working with an empty model and create your desired conceptual model. After the creation of the model, you could use the Generate Database Script from Model feature, which wasn't part of the Entity Framework 1 designer, to create the EDM storage and mapping schemas and also to generate a Data Definition Language (DDL) script. The generated DDL script could be used to create a database that would fit to the model according to a Model First workflow.

In the Entity Framework 1, the creation of the store schema definition language (SSDL), mapping specification language (MSL) and the script weren't available, so you needed to handcraft them, as well as create the database. Both of the approaches gave you a lot of flexibility while you built EDMs and could be used by the Entity Framework Designer. But they both forced you to use the designer and an .edmx file to create the EDM more easily.

The new Entity Framework Code First feature can help you use a more domain-driven approach while building your data tier on top of the Entity Framework. Microsoft said it expected to deliver the new functionality before the end of April 2011 -- so it should be available by the time you read this. In Code First, you can use only code without any designer or .edmx files to create the domain model. First you create Plain Old C# Object (POCO) classes that represent the domain model, and then you use a set of built-in tools like a fluent interface, data annotations and conventions in order to configure a runtime EDM for the domain model. Figure 1 summarizes the current Entity Framework development approaches.


[Click on image for larger view.]
Figure 1. Entity Framework development approaches.

This article will explain what the Code First development approach is all about and how to use it in order to implement your data-access layer. The article is based on the Entity Framework Feature community technology preview (CTP) 5, therefore things might change in the official release of Code First.

Let It Be Code
Code First was developed on top of Entity Framework 4 functionality as a stand-alone package. The idea behind it is to supply a simple API for an EDM runtime configuration, providing a second alternative to using .edmx files. The rationale behind the feature is that many developers, including myself, prefer to write code and use conventions instead of using XML files for configurations and modeling. It's faster, more productive, simpler and, of course, less error-prone than a hardcoded static-configuration file. This is why this approach is so essential in the development of a tool like the Entity Framework.

Another driver is domain-driven development principals. Using Code First enables the creation of a domain model without any concern about the persistence layer and how it's going to be implemented.

All you need to do is develop your domain model using POCO classes and let Code First figure out how to create the EDM from it (and even the database in some circumstances). This is implemented by a conventions engine that's built inside the Code First runtime. If you want to change Code First default conventions, there are a lot of extension points in the configuration process, such as a fluent interface API, data annotations and more.

DbContext and DbSet Classes
When starting to develop with Code First, you'll first encounter the new DbContext and DbSet classes. These classes represent a lightweight wrapper implementation on top of the Entity Framework ObjectContext and ObjectSet classes, respectively. You use the DbContext and DbSet classes as you used the ObjectContext and ObjectSet classes, but with less exposed Entity Framework API noise.

Also, there are some new methods that help implement common development needs, such as finding an entity or changing an entity state. If you aren't familiar with ObjectContext and ObjectSet, I suggest you to go to the following MSDN Library pages before you go on with the article: tinyurl.com/6bsoera and tinyurl.com/6988f55.

The DbContext is a main object in Code First that exposes the interaction between the Entity Framework and the database. Its responsibilities include database connectivity, change tracking, data persistence, entities caching and more. It's also a container of all the DbSets that you'll create in order to work against the database.

The DbSet is a collection representation of a set of entities. You can think about it as an in-memory representation of database records, but it's much more than that. It exposes a set of collection methods such as Add and Remove in order to manipulate the set's data. It also enables you to use LINQ to Entities to query its data.

The Domain Model
The first thing I encourage developers to do when they start using Code First is build their domain model. In order to build a domain model you need to build simple POCO classes and a database context that inherit from DbContext. You'll need to add a reference to the EntityFramework assembly, which is installed with the Entity Framework Feature CTP. In Listing 1 you can take a look at the model that I'm using here.

Listing 1 shows a simple model that includes companies and their associated employees. The interesting thing is the CompanyEntities, which is the context to the database. The context is playing the role as the database gateway, which will help to manage the entities' state, open connections and more. It includes two DbSets for each entity set that we have in the model. The entities will be placed in an entities assembly while the context will be placed in the Data Access Layer.

Using only this model is enough to get a runtime EDM. Code First will use its default conventions in order to achieve the building of the EDM during the execution of the application. These conventions include building primary keys out of properties that have the Id suffix, building foreign keys out of entities relations and more. Also, as a side effect, if a database or a connection string to an existing database doesn't exist, the Code First runtime will create a database in the SQL Express server of the current machine.

The calling to the constructor of DbContext with a string parameter, as in Listing 1, will force Code First to look at whether a connection string with the Manpower name exists. If the connection string exists then it will be used as a connection string to the database; otherwise the supplied string will be used as the database name. If the developer doesn't supply a database name, the convention of the database name is the namespace of the assembly followed by the name of the context (for example, DAL.CompanyEntities). Figure 2 shows the created database after running the model inside a simple console application.


[Click on image for larger view.]
Figure 2. The generated database.

As you can see, the database was created with all the relevant primary keys and foreign keys. Also, an EdmMetadata table was generated. This table is used by the DbContext in order to check whether the database schema matches the current model. Up until now I've done nothing to configure the generated runtime EDM. Let's dive into the EDM configurations.

Using DbModelBuilder and Code First Fluent API
One of the options to configure EDMs in Code First is a fluent API that's supplied through a class called DbModelBuilder. The DbModel-Builder role does all the heavy lifting of creating the EDM during runtime. Using the fluent API can help you configure the generated runtime EDM and shape it to your will.

The main way to configure the runtime generated model is by overriding the DbContext OnModelCreating method. The method gets a DbModelBuilder instance as a parameter, which is used to configure the model. The configuration phase occurs only once in the application, and the generated EDM is stored in the application cache. Listing 2 shows an example of how to write configurations with the fluent API.

First you override the OnModelCreating method in the custom DbContext that you've created. Then, for every aspect you want, you configure the DbModelBuilder using the fluent API. You first choose which element to configure: an entity or a complex type. The example shows how to configure entities by using the Entity generic method. The Entity method indicates on which entity to add the configurations while the ComplexType does the same for complex types.

Looking at Listing 2, you can see that in the Company entity the CompanyName is configured to be not null (required), with length of 50 characters and with a column of Name in the database instead of CompanyName. In the Employee entity the configuration is for the first and last names, which are not null and with type of varchar (the default behavior is nvarchar). Another method that can be used through the DbModelBuilder is the Ignore method, which indicates the entity/-complex type to ignore and therefore not created in the model.

The fluent API itself includes many other methods to configure the model such as working on relations, inheritance configurations and more. Most of these methods are self-explanatory and easy to follow. The DbModelBuilder fluent API isn't the only place that you can configure the model. Another way to configure the model is the use of model-configuration classes.

Model-Configuration Classes
Code First enables you to create dedicated classes for configuration purposes. In Listing 2 you saw a simple configuration in the OnModelCreating method. In the real world, a domain model can hold many entities and therefore the OnModelCreating can get crowded, bloated and hard to read. When that happens, it's time to refactor using the model-configuration classes.

The model-configuration classes are part of System.Data.Entity.ModelConfiguration namespace. There are two major classes that you'll use: the generic EntityTypeConfiguration and the generic ComplexTypeConfiguration. These classes expose the same Fluent API you used in the OnModelCreating method, but through the configuration class and not through the DbModelBuilder. In order to use this sort of configuration, you'll create a new class that will inherit from EntityTypeConfiguration for entities or Complex-Type-Configuration for complex types.

The following code shows the EmployeeTypeConfiguration class:

public class EmployeeTypeConfiguration : EntityTypeConfiguration<Employee>
{
  #region Ctor
  public EmployeeTypeConfiguration()
  {
    Property(e => e.FirstName).
      HasColumnType("varchar").
      IsRequired();
    Property(e => e.LastName).
      HasColumnType("varchar").
      IsRequired();
  }
  #endregion
}

The EmployeeTypeConfiguration holds the same configuration that existed in the OnModelCreating method. The only difference is that you don't use the DbModelBuilder and its Entity generic method. The configurations are being done in the constructor of the configuration class. To wire the configuration to the DbModelBuilder, you'll have to use the Add method of the DbModelBuilder Configuration collection.

The following line of code will do exactly that:

DbmodelBuilder.Configurations.Add(new EmployeeTypeConfiguration());

Another configuration method in Code First is the use of the data annotations assembly.

Data Annotations and Code First Integration
Data annotations aren't a new concept. The System.ComponentModel.DataAnnotations assembly is being widely used in a lot of frameworks such as ASP.NET MVC, Dynamic Data, WCF RIA Services and more. The data annotations are attributes that decorate properties and classes. They offer the ability to put cross-cutting concerns like validations outside the scope of the domain model and to decorate the model in order to impose these concerns.

In Code First, data annotations can be used to wire up configuration behavior into the model's POCO classes. Code First introduces more annotations to the data annotations assembly and uses some of the existing ones as well. The following code shows the employee entity from Listing 1, but decorated with data annotations:

[Table("CompanyEmployees")]
public class Employee
{
  #region Properties
  public int EmployeeId { get; set; }  
  public string FirstName { get; set; }
  public string LastName { get; set; }  
  [DataType(DataType.Date)]
  public DateTime HireDate { get; set; }  
  [NotMapped]
  public string Address { get; set; }
  public Company EmployedBy { get; set; }
  #endregion
}

In this code snippet, I use three annotations on the employee entity: Table, DataType and NotMapped. The Table annotation will configure the creation of a database table with the CompanyEmployees name instead of the default conventions that will create an Employees table. The DataType annotation will configure the field in the database to be of type date instead of datetime, which is the convention. The NotMapped annotation will indicate that the Address property won't be created as part of the EDM and in the database.

There are many annotations in the data annotations namespace. This list includes the currently supported data annotations in Code First:

  • KeyAttribute
  • StringLengthAttribute
  • MaxLengthAttribute
  • ConcurrencyCheckAttribute
  • RequiredAttribute
  • TimestampAttribute
  • ComplexTypeAttribute
  • ColumnAttribute
  • TableAttribute
  • InversePropertyAttribute
  • ForeignKeyAttribute
  • DatabaseGeneratedAttribute
  • NotMappedAttribute

Some might say that using data annotations pollutes the domain model, but in some cases -- such as validations -- they can help a lot.

Get Ready for Code First
Code First is a new development approach in the Entity Framework development stack. It enables the development of EDMs using only code and without the need for static .edmx files. It includes many features such as the fluent interface for configurations, conventions, data annotations integration and more. It may already be released by the time you read this, so expect to be able to employ it soon. Using Code First, you'll be able to simplify the understanding of your domain model and also make it more open for changes and maintenance. Code First upgrades the Entity Framework and takes it to the next level.

comments powered by Disqus

Featured

  • Compare New GitHub Copilot Free Plan for Visual Studio/VS Code to Paid Plans

    The free plan restricts the number of completions, chat requests and access to AI models, being suitable for occasional users and small projects.

  • Diving Deep into .NET MAUI

    Ever since someone figured out that fiddling bits results in source code, developers have sought one codebase for all types of apps on all platforms, with Microsoft's latest attempt to further that effort being .NET MAUI.

  • Copilot AI Boosts Abound in New VS Code v1.96

    Microsoft improved on its new "Copilot Edit" functionality in the latest release of Visual Studio Code, v1.96, its open-source based code editor that has become the most popular in the world according to many surveys.

  • AdaBoost Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the AdaBoost.R2 algorithm for regression problems (where the goal is to predict a single numeric value). The implementation follows the original source research paper closely, so you can use it as a guide for customization for specific scenarios.

  • Versioning and Documenting ASP.NET Core Services

    Building an API with ASP.NET Core is only half the job. If your API is going to live more than one release cycle, you're going to need to version it. If you have other people building clients for it, you're going to need to document it.

Subscribe on YouTube