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:
<connectionStrings>
<add name="Northwind"
connectionString="data
source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\northwind.mdf;User
Instance=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
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.