You can use a "convention over configuration" approach that enables database
persistence without having to explicitly configure anything. And, you can optionally
override the convention-based persistence and use a fluent code API to fully
customize your persistence mappings.
The CTP 5 will be the last preview build of Code First before the final release in
the first quarter of 2011. After installing the CTP all you need to do in order
to use it is to add a reference to the EntityFramework assembly into your project.
The namespace is System.Data.Entity. This will be found at :
C:\Program Files\Microsoft ADO.NET Entity Framework Feature CTP5\Binaries --or--
C:\Program Files (x86)\Microsoft ADO.NET Entity Framework Feature CTP5\Binaries on
an x64 machine.
The CTP 5 provides a number of enhancements over previous CTP's:
Better support for Existing Databases
Built-in Model-Level Validation and DataAnnotation Support
Fluent API Improvements
Pluggable Conventions Support
A Change Tracking API
Improved Concurrency Conflict Resolution
Raw SQL Query/Command Support
Code-First makes it easy to create model layers that work against existing databases.
First you create all your model classes (e.g., Person, Company, Product etc.) as
POCO (Plain Old CLR Object) classes.
Next, you provide a custom DbContext class. For example:
public class Northwind : DBContext
{
public DbSet<Product> Products {get;set;}
public DbSet<Category> Categories {get;set;}
}
Code-First enables your POCO classes to represent entities in your database, and
allows your model classes to be kept clean and free of dependencies. The DbContext
class provides public properties that map to the tables within the database.
Finally, you configure your database connection string in your config file:
<connectionStrings>
<add name="Northwind" connectionString="server=(local);Integrated Security=SSPI;database=Northwind;" providerName="System.Data.SqlClient" />
</connectionStrings>
Because the sample DbContext class is named 'Northwind', Code-First by default looks
for a “Northwind” connection string.
At this point, you are ready to query and update your database using the strongly-typed
model layer with EF Code First.
For example:
Northwind northwind = new Northwind();
var products = from p in northwind.Products
where p.Category.CategoryName = "Beverages"
select p;
The above returns a strongly-typed sequence of Product instances matching the query
criteria
You can also use the more compact LINQ syntax like this, which I prefer:
var quotes = model.Quotes.Select(q => q.Author.AuthorLastName.StartsWith("Franklin")).ToList();
Selecting a specific object, making changes and persisting it back to the database
is just as easy:
Northwind northwind = new Northwind();
Product product = northwind.Products.Find(1);
product.UnitPrice = 5.25M;
product.Discontinued =false;
northwind.SaveChanges();
CodeFirst takes care of all change - tracking and persistence work, making it a lot
easier for the developer to focus on the application and it's business logic
without having to spend hours on mindless database work.
Model Validation
This new release now includes built-in support for both the DataAnnotation and IValidationObject
approaches that are in .NET 4.0. This allows you to easily add validation rules
to your model classes and have them automatically validated during a Save operation
by the runtime. Validation logic is contained in the System.ComponentModel.DataAnnotations namespace, and can be used independently of Entity Framework. A simple example
of the use of DataAnnotations:
[Required(ErrorMessage="Last Name is required.")]
public string LastName {get;set;}
[Required(ErrorMessage="Age is required.")]
[Range(18, 120, Error Message="We don't allow minors.")]
public int Age {get;set;}
When you call SaveChanges() on your context, the DbEntityValidationException will be raised when there are any validation errors. This contains an EntityValidationErrors property that you can check and inform the user what needs to be done. If one of
your validation rules is violated, EF Code-First will abort the entire transaction
of changes, ensuring database consistency.
Other Improvements to EF Code-First
Code-First allows you to override the OnModelCreating method of the DbContext class to refine or override schema mapping rules. The ModelBuilder class that is passed to this method has new features that make defining mapping
rules more concise.
EF Code-First now provides support that allows you to override the default conventions
that EF uses, and replace them with your own set of conventions, in a manner
similar to the Fluent NHibernate offering. The Fluent API includes features that
allow you to specify primary keys, composite keys, making a type nullable, setting
the MaxLength of a string property, switching off Identity, defining complex
types, and defining relationships, table and column mappings, and more.
Code-First exposes a new set of change tracking features that lets you access the
Original, Current and Stored values, and the State (Added, Unchanged, Modified
or Deleted).
Better Exception messages are now provided and they allow access to the affected
object instance, making it easier to resolve conflicts.
Code-First now allows raw SQL queries and commands, including stored procedures,
that can be executed via the SqlQuery and SqlCommand methods on the DbContext.Database property. The results can be materialized into live object instances that can be
change-tracked by the DbContext.
You can download the EF Code-First CTP 5 here.
There is a lot more, including class name changes and known issues that you can read
up on at the ADO.NET Team blog here.
In order to exercise some of the above concepts, I've put together a simple ASP.NET
application along with a sample database I call "MiniQuotes" - that
contains three tables, Quotes, Subjects and Authors. To use this, just create
a new SQL Server database "QUOTESMINI" and run the supplied SQL script
against it. The script is in the web project "SQLScript" folder. This
is configured to use the SQL Server (local) instance - but if you want SQLEXPRESS,
simply reconfigure the connection string in the web.config.
No-Configuration AutoMapping
Now let's look at some cool "auto-mapping" that EF Code-First does for
us. Have a look at my Quote class from the downloadable sample:
public class Quote
{
public int ID { get; set; }
[StringLength(4000)]
[Required(ErrorMessage = "Quotation is required.")]
public string Quotation { get; set; }
[Required(ErrorMessage ="Subject is required.")]
public virtual Subject Subject { get; set; }
[Required(ErrorMessage ="Author is required.")]
public virtual Author Author { get; set; }
}
In order to get my Quote object to automatically put the correct matching Subject
in the Subject property, and the correct Author object in the Author property
of each Quote instance, all I need to do is declare the type of the property
and mark it as virtual. EF Code-First does everything else for me. No SQL to worry about, no foreign key constraints, no joins -- It just works.
If your Model class has a property that can hold multiple instances, simply define
it as virtual ICollection<type>.
Just in case you missed it, I never had to write a single line of SQL to create the sample app! And that will include all CRUD operations.
Performance-wise, Entity Framework (along with LINQ to SQL and similar offerings)
are not speed champions - so if you're developing an application where high performance
is an absolute must - you may be better off using raw SQL, either with or without
stored procedures. But for ease of use and "less is more" as a development
concept, Entity Framework with Code-First is a clear winner for me.
You can download the sample solution here.