Create The Contoso University Web Applicationhtml
Contoso University sample web applicatioin 是一個使用MVC4 & EF5 & VS2012建立的Sample網站。網站功能包括:學生入學,課程選擇,做業佈置。這一系列的教程會教咱們如何創建這個網站。jquery
Code First web
在Entiry Framework中,咱們有三種處理數據的方法:Database First,Model First,and Code First.這個教程中,咱們使用Code First。關於這三種之間的差異以及具體該選擇哪一種,能夠參考Entity Framework Development Workflows。數據庫
The Contoso University Web Applicationmvc
功能:用戶能夠查看,更新學生、課程、教師信息。app
這個Application的UI頁面,是系統自動生成的Template。因此咱們能夠關注於怎麼去用Entity Framework.以後咱們再用Kendo UI去更新咱們的UI。asp.net
準備(Prerequisits): Windows Azure SDK http://go.microsoft.com/fwlink/?LinkId=254364ide
一,建立一個MVC WEB Application學習
Create a new project named 「ContosoUniversity」,Using .NET Framework 4.5
網站樣式設置(Set Up The Site Style)
咱們會對網站的site menu,layout和home page作出一些更新
Views\Shared\_Layout.cshtml:更改母版頁的標題,增長一些鏈接
<!DOCTYPE html> <html lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <meta charset="utf-8" /> <title>@ViewBag.Title - Contoso University</title> <link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" /> <meta name="viewport" content="width=device-width" /> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") </head> <body> <header> <div class="content-wrapper"> <div class="float-left"> <p class="site-title">@Html.ActionLink("Contoso University", "Index", "Home")</p> </div> <div class="float-right"> <section id="login"> @Html.Partial("_LoginPartial") </section> <nav> <ul id="menu"> <li>@Html.ActionLink("首頁", "Index", "Home")</li> <li>@Html.ActionLink("關於", "About", "Home")</li> <li>@Html.ActionLink("學生", "Student", "Home")</li> <li>@Html.ActionLink("課程", "Course", "Home")</li> <li>@Html.ActionLink("教師", "Instructors", "Home")</li> <li>@Html.ActionLink("部門", "Departments", "Home")</li> </ul> </nav> </div> </div> </header> <div id="body"> @RenderSection("featured", required: false) <section class="content-wrapper main-content clear-fix"> @RenderBody() </section> </div> <footer> <div class="content-wrapper"> <div class="float-left"> <p>© @DateTime.Now.Year - Contoso University</p> </div> </div> </footer> @Scripts.Render("~/bundles/jquery") @RenderSection("scripts", required: false) </body> </html>
Views\Home\Index.cshtml:只保留如下這些:
Controllers\HomeController.cs:更改ViewBage.Message的內容:
public ActionResult Index() { ViewBag.Message = "Welcome to Contoso University"; return View(); }
Ctrl+F5運行:
二,爲Contoso University application 建立實體數據模型(Entity Data Model)
Model 中添加Entity Class:
1,添加Student.cs類:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ContosoUniversity.Models { public class Student { public int StudentID { get; set; } public string LastName { get; set; } public string FirstMidName { get; set; } public DateTime EnrollmentDate { get; set; } public virtual ICollection<Enrollment> Entrollments { get; set; } } }
2,添加Course.cs類
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Web; namespace ContosoUniversity.Models { public class Course { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int CourseID { get; set; } public string Title { get; set; } public int Credits { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } } }
3,添加Enrollment.cs類
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ContosoUniversity.Models { public enum Grade { A, B, C, D, F } public class Enrollment { public int EnrollmentID { get; set; } public int CourseID { get; set; } public int StudentID { get; set; } public Grade? Grade { get; set; } public virtual Course Course { get; set; } public virtual Student Student { get; set; } } }
三,建立數據上下文類(Create the Database Context)
數據庫上下文類是Model 中的實體數據模型(Data Model)和Entity Framework 之間的橋樑
Database context class類繼承自System.Data.Entity.DbContext 類,這裏面你須要指明哪些實體包含在data model 中。你一樣能夠自定義某些特定的Entity Framework behavior. 這個Project 中DbContext的類名爲SchoolContext
添加DAL文件夾,而後添加SchoolContext類:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace ContosoUniversity.Models { public enum Grade { A, B, C, D, F } public class Enrollment { public int EnrollmentID { get; set; } public int CourseID { get; set; } public int StudentID { get; set; } public Grade? Grade { get; set; } public virtual Course Course { get; set; } public virtual Student Student { get; set; } } }
DbContext類爲每個實體集(entity set)建立了一個DbSet屬性
每個實體集對應database中的一張table,每個實體對應
OnModelCreating方法中的modelBuilder.Conventions.Remove
防止表中的數據以複數(Students,Courses,Enrollments)命名。
四,SQL Server Express LocalDB
.mdf爲後綴的database文件,是一個單獨的文件放置於項目中的App_Data文件夾中。LocalDB不被推薦使用在web application中由於它不會和IIS一塊兒工做。在VS2012以及之後的版本中,LocalDB被默認安裝在VS中。
若是你是用.mdf存貯數據的話,須要更新web.config,添加連接字符串以下:
<add name="SchoolContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=ContosoUniversity;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\ContosoUniversity.mdf" providerName="System.Data.SqlClient" />
默認狀況下,Entiry Framework 會在webconfig中尋找和類名DbContext同名的鏈接字符串(這裏是SchoolContext),鏈接字符串就會指定APP_Data中一個命名爲ContosoUniversity.mdf的數據文件
若是你不手動在webconfig中添加這個鏈接字符串,Entity Framework就會自動給你添加一個鏈接字符串,可是這個database文件不會再App_Data文件中。
ConnectionStrings 中包含有名字爲DefaultConnection的默認的字符串鏈接,這個鏈接是用於Membership database的。在這個教程中咱們暫時不會用到membership database. 這兩種鏈接的不一樣之處就是數據庫名稱(database name)和屬性值(attribute value).
5、設置並執行Code First Migration . Set up and Execute a Code First Migration
在咱們開始開發項目的時候,咱們須要頻繁的更新Data Mode中的實體類(entity class ),每一次更新之後,Model 中的字段就和database中的字段不一致了。
因此咱們須要配置Entity Framework 來自動drop 或者re-create database來和model 中的實體類同步。這樣drop的方法來更新,在開發中咱們用的都是測試數據不會有什麼問題,可是一旦部署到正式環境,咱們就不能用這種方法去同步mode和database了。 Code First的Migrations功能可讓咱們更新數據庫結果,而且不用去drop 和 re-create database。
5.1 Enable Code First Migrations
1,Package Manager Console:
2,輸入命令:PM>enable-migrations -contexttypename SchoolContext
啓用成功,而且建立了Migrations文件夾以及Configurations.cs文件
當database在被created的時候以及每一次從Model中進行同步更新的時候,Configuration.cs中的Seed方法就會被調用。
Seed方法可讓咱們可以在Code First建立或者更新database之後,插入測試數據。
5.2 Set up Seed Method
namespace ContosoUniversity.Migrations { using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; using ContosoUniversity.Models; internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.DAL.SchoolContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(ContosoUniversity.DAL.SchoolContext context) { // This method will be called after migrating to the latest version. // You can use the DbSet<T>.AddOrUpdate() helper extension method // to avoid creating duplicate seed data. E.g. // // context.People.AddOrUpdate( // p => p.FullName, // new Person { FullName = "Andrew Peters" }, // new Person { FullName = "Brice Lambson" }, // new Person { FullName = "Rowan Miller" } // ); // var students = new List<Student>{ new Student { FirstMidName = "Carson", LastName = "Alexander", EnrollmentDate = DateTime.Parse("2010-09-01") }, new Student { FirstMidName = "Meredith", LastName = "Alonso", EnrollmentDate = DateTime.Parse("2012-09-01") }, new Student { FirstMidName = "Arturo", LastName = "Anand", EnrollmentDate = DateTime.Parse("2013-09-01") }, new Student { FirstMidName = "Gytis", LastName = "Barzdukas", EnrollmentDate = DateTime.Parse("2012-09-01") }, new Student { FirstMidName = "Yan", LastName = "Li", EnrollmentDate = DateTime.Parse("2012-09-01") }, new Student { FirstMidName = "Peggy", LastName = "Justice", EnrollmentDate = DateTime.Parse("2011-09-01") }, new Student { FirstMidName = "Laura", LastName = "Norman", EnrollmentDate = DateTime.Parse("2013-09-01") }, new Student { FirstMidName = "Nino", LastName = "Olivetto", EnrollmentDate = DateTime.Parse("2005-08-11") } }; students.ForEach(s => context.Students.AddOrUpdate(p => p.LastName, s)); context.SaveChanges(); var courses = new List<Course> { new Course {CourseID = 1050, Title = "Chemistry", Credits = 3, }, new Course {CourseID = 4022, Title = "Microeconomics", Credits = 3, }, new Course {CourseID = 4041, Title = "Macroeconomics", Credits = 3, }, new Course {CourseID = 1045, Title = "Calculus", Credits = 4, }, new Course {CourseID = 3141, Title = "Trigonometry", Credits = 4, }, new Course {CourseID = 2021, Title = "Composition", Credits = 3, }, new Course {CourseID = 2042, Title = "Literature", Credits = 4, } }; courses.ForEach(s => context.Courses.AddOrUpdate(p => p.Title, s)); context.SaveChanges(); var enrollments = new List<Enrollment> { new Enrollment { StudentID = students.Single(s => s.LastName == "Alexander").StudentID, CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID, Grade = Grade.A }, new Enrollment { StudentID = students.Single(s => s.LastName == "Alexander").StudentID, CourseID = courses.Single(c => c.Title == "Microeconomics" ).CourseID, Grade = Grade.C }, new Enrollment { StudentID = students.Single(s => s.LastName == "Alexander").StudentID, CourseID = courses.Single(c => c.Title == "Macroeconomics" ).CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Alonso").StudentID, CourseID = courses.Single(c => c.Title == "Calculus" ).CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Alonso").StudentID, CourseID = courses.Single(c => c.Title == "Trigonometry" ).CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Alonso").StudentID, CourseID = courses.Single(c => c.Title == "Composition" ).CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Anand").StudentID, CourseID = courses.Single(c => c.Title == "Chemistry" ).CourseID }, new Enrollment { StudentID = students.Single(s => s.LastName == "Anand").StudentID, CourseID = courses.Single(c => c.Title == "Microeconomics").CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Barzdukas").StudentID, CourseID = courses.Single(c => c.Title == "Chemistry").CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Li").StudentID, CourseID = courses.Single(c => c.Title == "Composition").CourseID, Grade = Grade.B }, new Enrollment { StudentID = students.Single(s => s.LastName == "Justice").StudentID, CourseID = courses.Single(c => c.Title == "Literature").CourseID, Grade = Grade.B } }; foreach (Enrollment e in enrollments) { var enrollmentInDataBase = context.Enrollments.Where( s => s.Student.StudentID == e.StudentID && s.Course.CourseID == e.CourseID).SingleOrDefault(); if (enrollmentInDataBase == null) { context.Enrollments.Add(e); } } context.SaveChanges(); } } }
Seed 方法,在Code First Migrations 建立database以及每一次從上次的migrations 進行update database的時候執行。Seed方法的目的是可讓你在application 讀取database數據以前向tables中insert data.
Seed方法中添加的數據大部分是測試用的,或者是一些發佈到正式環境也必須有的數據,例如部門信息等,這樣咱們在開發的時候就不用每一次都手動的進行添加數據。
1,更新Seed方法,這樣程式運行的時候就會加載這些測試數據
Seed方法把database context對象做爲輸入參數,而後添加新的實體到database中。對於每個實體類型來講,code首先建立了實體的集合(list),而後把他們添加到對應的DbSet屬性中,而後用SaveChange()方法保存到database.
AddOrUpdate方法執行了一個插入更新的動做。每一次Mirgraiton的時候Seed方法都會執行,它會把開發測試過程當中的更新重寫到database中。
context.Students.AddOrUpdate(p => p.LastName, s)
AddOrUpate中的第一個參數,指定根據這個參數的屬性去檢查實體數據是否存在。在測試的Student data中,咱們用LastName,由於在List的列表中,LastName是惟一的。
若是咱們添加一條LastName重複名稱的student.當你進行database migrations的時候就會報出下面的錯誤:
Sequence contains more than one element
foreach (Enrollment e in enrollments) { var enrollmentInDataBase = context.Enrollments.Where( s => s.Student.StudentID == e.StudentID && s.Course.CourseID == e.CourseID).SingleOrDefault(); if (enrollmentInDataBase == null) { context.Enrollments.Add(e); } } context.SaveChanges();
Seed方法中添加Enrollment Entities的時候,並無用到AddOrUpdate方法。
而是用了Add,這個方法會檢查enrollment 實體數據是否存在,不存在的話加入一條新的數據,若是存在不會對其進行更新。Foreach循環遍歷 Enrollment中的每個實體,在你第一次update database的時候,這些實體就會被添加到database中。
2.Ctrl+Shift+B重建解決方案:
5.3 Create and Execute the First Migration建立並執行遷移
1,Package Manager Console中輸入命令建立最開始的遷移,並更新
1. PM>add-migration InitialCreate
2. PM>update-database
add-migration 命令添加了Migrations文件夾,而且包含遷移類文件,遷移類生成了database. InitialCreate是本身定義的參數名字。
遷移類中的Up方法,建立了和Model Class中實體集合(entity sets)對應的database tables. Down方法是刪除這些實體。Migrations調用Up方法去執行data model 中的改變。當你Update-database的時候,Migrations調用了Down方法。
update-database
先調用
Up
方法建立數據庫,而後調用
Seed
方法把數據填充到數據庫中。
完成以上,咱們便在App_Data中建立了一個.mdf後綴的SQL Server 數據庫文件。.mdf文件的名字是咱們在webconfig的鏈接字符串中定義的。
咱們看到資料庫和.mdf文件:
6、Creating a Student Controller and Views
總結:
咱們建立了一個簡單的application。接下來,咱們會學習如何執行CRUD(create,read,update,delete)。
C#基礎: