This week the data team released the CTP5 build of the new Entity Framework Code-First library. EF Code-First enables a pretty sweet code-centric development workflow for working with data. It enables you to:
- Develop without ever having to open a designer or define an XML mapping file
- Define model objects by simply writing “plain old classes” with no base classes required
- Use a “convention over configuration” approach that enables database persistence without explicitly configuring anything
- Optionally override the convention-based persistence and use a fluent code API to fully customize the persistence mapping
I’m a big fan of the EF Code-First approach, and wrote several blog posts about it this summer:
Today’s new CTP5 release delivers several nice improvements over the CTP4 build, and will be the last preview build of Code First before the final release of it. We will ship the final EF Code First release in the first quarter of next year (Q1 of 2011). It works with all .NET application types (including both ASP.NET Web Forms and ASP.NET MVC projects).
Installing EF Code First
You can install and use EF Code First CTP5 using one of two ways:
Approach 1) By downloading and running a setup program. Once installed you can reference the EntityFramework.dll assembly it provides within your projects.
Approach 2) By using the NuGet Package Manager within Visual Studio to download and install EF Code First within a project. To do this, simply bring up the NuGet Package Manager Console within Visual Studio (View->Other Windows->Package Manager Console) and type “Install-Package EFCodeFirst”:
Typing “Install-Package EFCodeFirst” within the Package Manager Console will cause NuGet to download the EF Code First package, and add it to your current project:
Doing this will automatically add a reference to the EntityFramework.dll assembly to your project:
NuGet enables you to have EF Code First setup and ready to use within seconds. When the final release of EF Code First ships you’ll also be able to just type “Update-Package EFCodeFirst” to update your existing projects to use the final release.
EF Code First Assembly and Namespace
The CTP5 release of EF Code First has an updated assembly name, and new .NET namespace:
- Assembly Name: EntityFramework.dll
- Namespace: System.Data.Entity
These names match what we plan to use for the final release of the library.
Nice New CTP5 Improvements
The new CTP5 release of EF Code First contains a bunch of nice improvements and refinements. Some of the highlights include:
- Better support for Existing Databases
- Built-in Model-Level Validation and DataAnnotation Support
- Fluent API Improvements
- Pluggable Conventions Support
- New Change Tracking API
- Improved Concurrency Conflict Resolution
- Raw SQL Query/Command Support
The rest of this blog post contains some more details about a few of the above changes.
Better Support for Existing Databases
EF Code First makes it really easy to create model layers that work against existing databases. CTP5 includes some refinements that further streamline the developer workflow for this scenario.
Below are the steps to use EF Code First to create a model layer for the Northwind sample database:
Step 1: Create Model Classes and a DbContext class
Below is all of the code necessary to implement a simple model layer using EF Code First that goes against the Northwind database:
EF Code First enables you to use “POCO” – Plain Old CLR Objects – to represent entities within a database. This means that you do not need to derive model classes from a base class, nor implement any interfaces or data persistence attributes on them. This enables the model classes to be kept clean, easily testable, and “persistence ignorant”. The Product and Category classes above are examples of POCO model classes.
EF Code First enables you to easily connect your POCO model classes to a database by creating a “DbContext” class that exposes public properties that map to the tables within a database. The Northwind class above illustrates how this can be done. It is mapping our Product and Category classes to the “Products” and “Categories” tables within the database. The properties within the Product and Category classes in turn map to the columns within the Products and Categories tables – and each instance of a Product/Category object maps to a row within the tables.
The above code is all of the code required to create our model and data access layer! Previous CTPs of EF Code First required an additional step to work against existing databases (a call to Database.Initializer<Northwind>(null) to tell EF Code First to not create the database) – this step is no longer required with the CTP5 release.
Step 2: Configure the Database Connection String
We’ve written all of the code we need to write to define our model layer. Our last step before we use it will be to setup a connection-string that connects it with our database. To do this we’ll add a “Northwind” connection-string to our web.config file (or App.Config for client apps) like so:
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\northwind.mdf;User Instance=true"
EF “code first” uses a convention where DbContext classes by default look for a connection-string that has the same name as the context class. Because our DbContext class is called “Northwind” it by default looks for a “Northwind” connection-string to use. Above our Northwind connection-string is configured to use a local SQL Express database (stored within the \App_Data directory of our project). You can alternatively point it at a remote SQL Server.
Step 3: Using our Northwind Model Layer
We can now easily query and update our database using the strongly-typed model layer we just built with EF Code First.
The code example below demonstrates how to use LINQ to query for products within a specific product category. This query returns back a sequence of strongly-typed Product objects that match the search criteria:
The code example below demonstrates how we can retrieve a specific Product object, update two of its properties, and then save the changes back to the database:
EF Code First handles all of the change-tracking and data persistence work for us, and allows us to focus on our application and business logic as opposed to having to worry about data access plumbing.
Built-in Model Validation
EF Code First allows you to use any validation approach you want when implementing business rules with your model layer. This enables a great deal of flexibility and power.
Starting with this week’s CTP5 release, EF Code First also now includes built-in support for both the DataAnnotation and IValidatorObject validation support built-into .NET 4. This enables you to easily implement validation rules on your models, and have these rules automatically be enforced by EF Code First whenever you save your model layer. It provides a very convenient “out of the box” way to enable validation within your applications.
Applying DataAnnotations to our Northwind Model
The code example below demonstrates how we could add some declarative validation rules to two of the properties of our “Product” model:
We are using the [Required] and [Range] attributes above. These validation attributes live within the System.ComponentModel.DataAnnotations namespace that is built-into .NET 4, and can be used independently of EF. The error messages specified on them can either be explicitly defined (like above) – or retrieved from resource files (which makes localizing applications easy).
Validation Enforcement on SaveChanges()
EF Code-First (starting with CTP5) now automatically applies and enforces DataAnnotation rules when a model object is updated or saved. You do not need to write any code to enforce this – this support is now enabled by default.
This new support means that the below code – which violates our above rules – will automatically throw an exception when we call the “SaveChanges()” method on our Northwind DbContext:
The DbEntityValidationException that is raised when the SaveChanges() method is invoked contains a “EntityValidationErrors” property that you can use to retrieve the list of all validation errors that occurred when the model was trying to save. This enables you to easily guide the user on how to fix them. Note that EF Code-First will abort the entire transaction of changes if a validation rule is violated – ensuring that our database is always kept in a valid, consistent state.
EF Code First’s validation enforcement works both for the built-in .NET DataAnnotation attributes (like Required, Range, RegularExpression, StringLength, etc), as well as for any custom validation rule you create by sub-classing the System.ComponentModel.DataAnnotations.ValidationAttribute base class.
UI Validation Support
A lot of our UI frameworks in .NET also provide support for DataAnnotation-based validation rules. For example, ASP.NET MVC, ASP.NET Dynamic Data, and Silverlight (via WCF RIA Services) all provide support for displaying client-side validation UI that honor the DataAnnotation rules applied to model objects.
The screen-shot below demonstrates how using the default “Add-View” scaffold template within an ASP.NET MVC 3 application will cause appropriate validation error messages to be displayed if appropriate values are not provided:
ASP.NET MVC 3 supports both client-side and server-side enforcement of these validation rules. The error messages displayed are automatically picked up from the declarative validation attributes – eliminating the need for you to write any custom code to display them.
Keeping things DRY
The “DRY Principle” stands for “Do Not Repeat Yourself”, and is a best practice that recommends that you avoid duplicating logic/configuration/code in multiple places across your application, and instead specify it only once and have it apply everywhere.
EF Code First CTP5 now enables you to apply declarative DataAnnotation validations on your model classes (and specify them only once) and then have the validation logic be enforced (and corresponding error messages displayed) across all applications scenarios – including within controllers, views, client-side scripts, and for any custom code that updates and manipulates model classes.
This makes it much easier to build good applications with clean code, and to build applications that can rapidly iterate and evolve.
Other EF Code First Improvements New to CTP5
EF Code First CTP5 includes a bunch of other improvements as well. Below are a few short descriptions of some of them:
EF Code First allows you to override an “OnModelCreating()” method on the DbContext class to further refine/override the schema mapping rules used to map model classes to underlying database schema. CTP5 includes some refinements to the ModelBuilder class that is passed to this method which can make defining mapping rules cleaner and more concise. The ADO.NET Team blogged some samples of how to do this here.
- Pluggable Conventions Support
EF Code First CTP5 provides new support that allows you to override the “default conventions” that EF Code First honors, and optionally replace them with your own set of conventions.
EF Code First CTP5 exposes a new set of change tracking information that enables you to access Original, Current & Stored values, and State (e.g. Added, Unchanged, Modified, Deleted). This support is useful in a variety of scenarios.
- Improved Concurrency Conflict Resolution
EF Code First CTP5 provides better exception messages that allow access to the affected object instance and the ability to resolve conflicts using current, original and database values.
- Raw SQL Query/Command Support
EF Code First CTP5 now allows raw SQL queries and commands (including SPROCs) to be executed via the SqlQuery and SqlCommand methods exposed off of the DbContext.Database property. The results of these method calls can be materialized into object instances that can be optionally change-tracked by the DbContext. This is useful for a variety of advanced scenarios.
- Full Data Annotations Support
EF Code First CTP5 now supports all standard DataAnnotations within .NET, and can use them both to perform validation as well as to automatically create the appropriate database schema when EF Code First is used in a database creation scenario.
EF Code First provides an elegant and powerful way to work with data. I really like it because it is extremely clean and supports best practices, while also enabling solutions to be implemented very, very rapidly. The code-only approach of the library means that model layers end up being flexible and easy to customize.
This week’s CTP5 release further refines EF Code First and helps ensure that it will be really sweet when it ships early next year. I recommend using NuGet to install and give it a try today. I think you’ll be pleasantly surprised by how awesome it is.
Hope this helps,