Code First Development with the ADO.Net Entity Framework in
EF Feature CTP4
Hands-on Lab
Manual
Code First Development with the ADO.Net Entity Framework
Microsoft Hands-on Labs
Page 3 of 22
Information in this document, including URL and other Internet Web site references, is subject to change without notice. Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places, and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, place, or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
The names of manufacturers, products, or URLs are provided for informational purposes only and Microsoft makes no representations and warranties, either expressed, implied, or statutory, regarding these manufacturers or the use of the products with any Microsoft technologies. The inclusion of a manufacturer or product does not imply endorsement of Microsoft of the manufacturer or product. Links are provided to third party sites. Such sites are not under the control of Microsoft and Microsoft is not responsible for the contents of any linked site or any link contained in a linked site, or any changes or updates to such sites. Microsoft is not responsible for webcasting or any other form of transmission received from any linked site. Microsoft is providing these links to you only as a convenience, and the inclusion of any link does not imply endorsement of Microsoft of the site or the products contained therein.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
Copyright © 2007 Microsoft Corporation. All rights reserved.
Microsoft are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.
Version 1.2
Table of Contents
Lab Introduction 5
Objectives 5
Prerequisites 5
Lab Scenarios 5
Virtual PC Configuration and Setup 6
Copy/Paste of Code 6
Exercise 1: Basic Data Access 7
Exercise 2: Evolving the Domain Model 14
Exercise 3: Testing 17
Additional Resources 22
Copyright 23
Code First Development with the ADO.Net Entity Framework
Microsoft Hands-on Labs
Page 3 of 22
Lab Introduction
Code First Development with the ADO.Net Entity Framework
Microsoft Hands-on Labs
Page 3 of 22
Each Exercise in this lab is designed to be completed independently if you do not have time to complete all Exercises in one sitting.
Objectives
/ After completing these self-paced labs, you will be able to:§ Perform basic data access using the Code First development pattern with the Productivity Improvements for the ADO.Net Entity Framework (EF).
§ Keep your database schema in sync as your domain model evolves.
§ Test your application components using a separate test database with well-known seed data.
Prerequisites
/ § Experience with Visual Studio§ Experience with writing LINQ queries
§ General experience with MVC is helpful but not required
Lab Scenarios
/ This series of exercises is designed to show you how to get started using the Code First development pattern with the ADO.Net Entity Framework. Exercises can be completed as a sequence or can be completed independently.Suggested Time for Completion: 30 minutes
Code First Development with the ADO.Net Entity Framework
Microsoft Hands-on Labs
Page 21 of 22
Virtual PC Configuration and Setup
The Virtual PC machine name is DataDevLab10EFCodeFirstLab.
The accounts and passwords used in the following exercises are shown in the following table:
Account Name / Account Password / Account UsageDataDev / passw0rdpassw0rd / Login account for EFProdLab computer
Copy/Paste of Code
You will have the option to copy/paste code snippets from this document to complete this lab. In order to do this, you need to open a copy of this lab manual inside the Virtual Machine. This specific lab can be found here: C:\HOLs\ EF Productivity Improvements\.
Exercise 1: Basic Data Access
In this exercise, you will create a simple domain model for Blogs and Posts using CLR classes. You will then use these objects for data access in an MVC application using the Code First development pattern.
Tasks / Detailed Steps /Create an Empty MVC Application / 1. Start Visual Studio
From the Windows task bar, select Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 menu item
2. When Microsoft Visual Studio 2010 opens, create a new Empty MVC2 Application Project
From the File menu, select New | Project…
3. In the New Project dialog, select Visual C# | Web| ASP.NET MVC 2 Empty Web Application
Fill in the names and location for the project:
Name / Blogging
Location / C:\HOLs\Entity Framework\C:\HOLs\EF Productivity Improvements\Exercise1\
Solution Name / Blogging
4. Click OK to create the project
Build the Domain Model / In this step you will build a domain model using POCO (Plain Old CLR Object) classes, these classes have no dependency on the ADO.Net Entity Framework.
5. From the Solution Explorer, right-click on the Models folder and select Add | Class …
This opens the Add New Item dialog
6. In the Add New Item dialog, give the class the name “Blog.cs”
Click Add to add the class to your project
7. Implement the Blog class as follows:
Note: We are annotating the primary key property with the [ScaffoldColumn(false)] to let MVC know that the user does not need to supply this value
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Blogging.Models
{
public class Blog
{
[ScaffoldColumn(false)]
public int BlogId { get; set; }
public string Name { get; set; }
public string Owner { get; set; }
public virtual ICollectionPost> Posts { get; set; }
}
}
8. Repeat steps 5 & 6 to add another classed called “Post.cs”
9. Implement the Post class as follows:
using System.ComponentModel.DataAnnotations;
namespace Blogging.Models
{
public class Post
{
[ScaffoldColumn(false)]
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual Blog Blog { get; set; }
}
}
Reference the EF Feature CTP4 Assembly / The Productivity Improvement features are currently in preview form and reside in a separate assembly from the core ADO.Net Entity Framework components. In this step you will add a reference to the assembly that contains these preview components.
10. From the Solution Explorer, right-click on the References folder and select Add Reference…
This opens the Add Reference dialog
11. Select the .NET tab
12. Select Microsoft.Data.Entity.Ctp from the list
Note: you will have to wait for a few seconds as the list is populated
13. Click OK to add the reference
Build a Derived DbContext / In this step you will create a context that derives from DbContext and exposes a DbSet<TEntity> for each type in the domain model. DbContext will automatically discover the model at runtime based on the DbSet properties. After discovering the model DbContext will then locate a database to use and create the schema to support the model, this is known as Code First development.
You can change the database that the DbContext will connect to and alter the shape of the database schema that is generated but that is beyond the scope of this lab, see the Additional Resources section for more information on this functionality.
14. From the Solution Explorer, right-click on the Models folder and select Add | Class …
This opens the Add New Item dialog
15. In the Add New Item dialog, give the class the name “BloggingContext.cs”
Click Add to add the class to your project
16. Implement the BloggingContext class as follows:
using System.Data.Entity;
namespace Blogging.Models
{
public class BloggingContext : DbContext
{
public DbSetBlog> Blogs { get; set; }
public DbSetPost> Posts { get; set; }
}
}
Create a Blog Controller / In this step you will create an MVC controller that uses the domain model and derived context to query and persist data. This step will introduce you to the simplified API surface of DbContext and DbSet<TEntity>.
17. From the Solution Explorer, right-click the Controllers folder and select Add | Controller …
This opens the Add Controller dialog
18. In the Add Controller dialog, give the controller the name “BlogController”
19. Check the “Add actions methods…” check-box
20. Click Add to add the controller to your project
21. Implement the BlogController as follows:
Note: The return type of the Get methods is changed from ActionResult to ViewResult to help with testing in Exercise 3.
using System.Linq;
using System.Web.Mvc;
using Blogging.Models;
namespace Blogging.Controllers
{
public class BlogController : Controller
{
private BloggingContext context = new BloggingContext();
//
// GET: /Blog/
public ViewResult Index()
{
// Use a LINQ query against a DbSet<Blog>
// to select all blogs ordered by Name
var blogs = from b in context.Blogs
orderby b.Name
select b;
return View(blogs.ToList());
}
//
// GET: /Blog/Details/5
public ViewResult Details(int id)
{
// Load the existing blog from the database
return View(context.Blogs.Find(id));
}
//
// GET: /Blog/Create
public ViewResult Create()
{
return View(new Blog());
}
//
// POST: /Blog/Create
[HttpPost]
public ActionResult Create(Blog b)
{
// Add the newly created blog
context.Blogs.Add(b);
// Persist changes to the database
context.SaveChanges();
return RedirectToAction("Index");
}
//
// GET: /Blog/Edit/5
public ViewResult Edit(int id)
{
// Load the existing blog from the database
return View(context.Blogs.Find(id));
}
//
// POST: /Blog/Edit/5
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
// Load the existing blog from the database
var b = context.Blogs.Find(id);
// Apply the new values from the form
UpdateModel(b);
// Persist changes to the database
context.SaveChanges();
return RedirectToAction("Index");
}
//
// GET: /Blog/Delete/5
public ViewResult Delete(int id)
{
// Load the existing blog from the database
return View(context.Blogs.Find(id));
}
//
// POST: /Blog/Delete/5
[HttpPost]
public ActionResult Delete(int id, FormCollection collection)
{
// Load the existing blog from the database
var b = context.Blogs.Find(id);
// Delete the blog
context.Blogs.Remove(b);
// Persist changes to the database
context.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
// Make sure the context gets disposed
if (disposing)
{
context.Dispose();
}
base.Dispose(disposing);
}
}
}
Make Blog the Default Controller / In this step you will set the Blog controller as the default controller so that a list of blogs is displayed when the MVC application is run.
22. From the Solution Explorer, open (double-click) on the Global.asax file
23. Replace the default controller with the Blog controller (highlighted below):
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
Add Views for the Blog Controller / Views provide a graphical user interface over the controller. Views are not directly related to data access so in this step you will add some pre-built views to your project.
24. From the Solution Explorer, right-click on the Views folder and select Add | New Folder
25. Name the folder “Blog”
26. Right-click on the newly created Blog folder and select Add Existing Item…
This opens the Add Existing Item dialog
27. Navigate to “C:\HOLs\EF Productivity Improvements\Blog Views”
28. Select all the items in this folder (ctrl + A)
29. Click Add to add the views to your project.
Run the Application / 30. Press F5 to run the Blog Application
31. Use the web interface to create some sample data
Exercise 2: Evolving the Domain Model
In this exercise you will modify your domain model and then use database initializers to allow the database schema to be updated to reflect the changes to your domain model.
Tasks / Detailed Steps /Open the Project File / If you are continuing from Exercise 1 then you can skip to step 4.
1. Start Visual Studio.
From the Windows task bar, select Start | All Programs | Microsoft Visual Studio 2010 | Microsoft Visual Studio 2010 menu item
2. Open the project
From the File menu, select File | Open | Project/Solution menu item.
3. From the Open Project dialog, open the solution file at C:\HOLs\EF Productivity Improvements \Exercise2\Blogging\Blogging.sln
4. Press F5 to run the application
Note: This is important because the rest of this exercise depends on the database from Exercise 1 being created.
Change the Model / In this step you will make some changes to your domain model. You will use data annotations to mark the Name property of Blog as required with a maximum length of 50 characters. By default DbContext will not alter the database schema and you will receive an exception because the domain model is no longer compatible with the database.
5. From the Solution Explorer, open (double-click) on the Models\Blog.cs file
6. Add the [Required] and [MaxLength(50)] data annotations to the Name property:
public class Blog
{
[ScaffoldColumn(false)]
public int BlogId { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
public string Owner { get; set; }
public ICollectionPost> Posts { get; set; }
}
7. Press F5 to run the application
8. You will receive the following exception:
Set a Database Initializer / In this step you will set a database initializer for your derive context that will drop and recreate the database whenever the domain model changes.
9. From the Solution Explorer, open (double-click) on the Global.asax file
10. Add using statements for “System.Data.Entity.Infrastructure” and “Blogging.Models”
using System.Data.Entity.Infrastructure;
using Blogging.Models;
11. In the Application_Start method, set the initializer for the BloggingContext to recreate the database when the model changes:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
Database.SetInitializerBloggingContext(
new RecreateDatabaseIfModelChangesBloggingContext>());
}
12. Press F5 to run the application
Exercise 3: Testing
In this exercise you will write a test for your MVC controller. The test will run against a SQL Compact database and the database will be recreated with a well-known set of test data before each run.