你會在這些教程中構建的應用程序是一個簡單的大學網站。css
用戶能夠查看和更新學生、 課程和教師信息。這裏有幾個屏幕,您將建立。html
這個網站的用戶界面樣式一直接近由內置的模板,生成的內容,以便本教程能夠集中主要精力如何使用實體框架。jquery
方向和屏幕截圖在本教程中假定您正在使用Visual Studio 2012或Visual Studio 2012 速成網站,最新的更新與截至 2013 年 7 月,安裝的 Windows Azure SDK。你能夠獲得這一切與下面的連接:web
Windows Azure SDK 以 Visual Studio 2012ajax
若是你有安裝了 Visual Studio,上面的連接將安裝任何缺乏的組件。若是你沒有 Visual Studio,該連接將安裝 Visual Studio 2012 速成網站。您可使用 Visual Studio 2013 年,但某些所需的程序和屏幕會有所不一樣。sql
打開 Visual Studio 並建立一個新 C# 項目命名爲"ContosoUniversity"使用ASP.NET MVC 4 Web 應用程序模板。請確保您的目標.NET 框架 4.5 (你會使用enum
的屬性,而且,須要.NET 4.5)。數據庫
在新的 ASP.NET MVC 4 項目對話框中選擇的互聯網應用模板。express
Razor視圖引擎選擇,和建立一個單元測試項目的複選框處於清除狀態的假期。canvas
單擊肯定.api
幾個簡單的改變將設立網站菜單、 佈局和主頁。
打開Views\Shared\_Layout.cshtml,而後用如下代碼替換該文件的內容。突出顯示所作的更改。
<!DOCTYPE html> <html lang="en"> <head> <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("Home", "Index", "Home")</li> <li>@Html.ActionLink("About", "About", "Home")</li> <li>@Html.ActionLink("Students", "Index", "Student")</li> <li>@Html.ActionLink("Courses", "Index", "Course")</li> <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li> <li>@Html.ActionLink("Departments", "Index", "Department")</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,用如下代碼,以消除有關 ASP.NET 和 MVC 模板段落替換該文件的內容:
@{
ViewBag.Title = "Home Page";
}
@section featured {
<section class="featured"> <div class="content-wrapper"> <hgroup class="title"> <h1>@ViewBag.Title.</h1> <h2>@ViewBag.Message</h2> </hgroup> </div> </section> }
在Controllers\HomeController.cs,將值更改成ViewBag.Message
Index
操做方法中爲"歡迎來到 Contoso 大學 !",以下面的示例所示:
public ActionResult Index() { ViewBag.Message = "Welcome to Contoso University"; return View(); }
按 CTRL + F5 以運行網站。你看到主頁與主菜單。
接下來,您將建立實體類爲 Contoso University 中的應用。你將開始與如下三個實體:
還有Student
和Enrollment
實體之間的一個一對多關係和Course
和Enrollment
實體之間是一對多的關係。換句話說,學生能夠在任意數量的課程,並固然能夠有任意數量的學生參加了它。
在如下部分中,您將建立一個類,用於每一個這些實體。
注若是您嘗試編譯該項目,在您完成全部這些實體類的建立以前,你就會獲得編譯器錯誤。
在模型文件夾中,建立Student.cs和現有代碼替換爲如下代碼:
using System; using System.Collections.Generic; 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> Enrollments { get; set; } } }
StudentID
屬性將成爲此類對應的數據庫表的主鍵列。默認狀況下,實體框架將解釋是命名的ID
或類名ID
做爲主鍵的屬性。
Enrollments
屬性是一個導航屬性。導航屬性持有此實體相關的其餘實體。在這種狀況下,一個Student
實體的Enrollments
屬性將保留全部的Enrollment
實體的那個Student
實體相關的。換言之,若是某一給定的Student
行在數據庫中有兩個相關的Enrollment
行 (包含在其StudentID
的外鍵列中的那個學生主鍵值的行),該Student
實體Enrollments
導航屬性將包含這兩個Enrollment
實體。
導航屬性一般定義爲virtual
中,以便他們能夠利用某些實體框架功能,如延遲加載。(延遲加載將稍後解釋,讀取相關數據教程稍後在本系列中。
若是一個導航屬性能夠容納多個實體 (如多多或一個一對多關係),其類型必須是一個列表條目能夠被添加、 刪除和更新,如ICollection
.
在模型文件夾中,建立Enrollment.cs和現有代碼替換爲如下代碼:
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; } } }
等級屬性是枚舉。問號後Grade
類型聲明指示Grade
屬性是能夠爲 null。爲 null 的品位是不一樣於零級 — — null 意味着等級鮮爲人知或沒有被指派。
StudentID
屬性是一個外鍵,且相應的導航屬性是Student
。Enrollment
實體是與一個Student
實體相關聯,因此該屬性只能容納一個單一的Student
實體 (不像Student.Enrollments
導航屬性你前面所述,而數組能夠存放多個Enrollment
實體)。
CourseID
屬性是一個外鍵,且相應的導航屬性Course
。Enrollment
實體是與一個Course
實體相關聯。
在模型文件夾中,建立Course.cs,現有代碼替換爲如下代碼:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; 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; } } }
Enrollments
屬性是一個導航屬性。Course
實體能夠與任意數量的Enrollment
實體。
咱們會說更多關於[DatabaseGenerated(DatabaseGeneratedOption.None)]
在接下來的教程中的屬性。基本上,此屬性容許您爲該課程而不是生成的數據庫輸入的主鍵。
座標給定的數據模型的實體框架功能的主類是數據庫上下文類。經過從System.Data.Entity.DbContext類派生來建立此類。在您的代碼中您指定數據模型中包括哪些實體。您還能夠自定義某些實體框架行爲。在這個項目中,類名爲SchoolContext
.
建立一個文件夾命名DAL (爲數據訪問層)。在該文件夾中建立一個新的類文件,命名爲SchoolContext.cs,和現有的代碼替換爲如下代碼:
using ContosoUniversity.Models; using System.Data.Entity; using System.Data.Entity.ModelConfiguration.Conventions; namespace ContosoUniversity.DAL { public class SchoolContext : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Enrollment> Enrollments { get; set; } public DbSet<Course> Courses { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } } }
此代碼建立一個DbSet屬性爲每一個實體集。在實體框架術語中,實體集一般對應於數據庫表,和一個實體對應於表中的一行。
OnModelCreating方法中的modelBuilder.Conventions.Remove
語句能夠防止表名稱正在趨向多元化。若是你不這樣作,所生成的表將命名爲Students
、Courses
和Enrollments
。相反,表名稱將是Student
、Course
、 及Enrollment
。表名稱應該多數開發商不一樣意。本教程使用的是單數形式,但重要的一點是您能夠選擇哪一個你更喜歡經過包括或省略下面這行代碼的形式。
LocalDB是一個輕量級版本 SQL Server 表示數據庫引擎的按需啓動和運行在用戶模式下。LocalDB 運行的 SQL Server Express 使您可以使用數據庫的.mdf文件做爲特殊的執行方式。一般狀況下,LocalDB 數據庫文件保存在 web 項目的App_Data文件夾中。在 SQL Server Express用戶實例功能還使您可以使用.mdf文件,但不推薦使用用戶實例的功能 ;所以,LocalDB 被推薦使用的.mdf文件。
一般 SQL Server Express 的並不用於生產的 web 應用程序。LocalDB 尤爲不推薦用於生產一個 web 應用程序由於它不設計工做的非法入境者。
在 Visual Studio 2012 及之後的版本中,默認狀況下,Visual Studio 安裝 LocalDB。在 Visual Studio 2010 及更早版本中,在默認狀況下,Visual Studio ; 安裝 SQL Server Express (無 LocalDB)您必須手動安裝它,若是你使用的 Visual Studio 2010。
在本教程中您將使用 LocalDB,以便數據庫能夠存儲在.mdf文件所在的App_Data文件夾中。打開根Web.config文件併到connectionStrings
集合中,添加一個新的鏈接字符串,以下面的示例所示。(請確保您更新Web.config文件中的根項目文件夾。此外,還有 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" />
默認狀況下,實體框架查找名爲DbContext
類 (此項目SchoolContext
) 相同的鏈接字符串。您已經添加的鏈接字符串指定一個名爲ContosoUniversity.mdf位於App_Data文件夾中的 LocalDB 數據庫。更多的信息,請參見ASP.NET Web 應用程序的 SQL 服務器鏈接字符串.
實際上,您不須要指定的鏈接字符串。若是您不提供鏈接字符串,實體框架將建立一個爲您 ;可是,數據庫可能沒法在您的應用程序的App_data文件夾中。將建立數據庫的信息,請參見代碼第一次到新的數據庫.
connectionStrings
集合還具備一個名爲DefaultConnection
的用於成員資格數據庫的鏈接字符串。在本教程中,您不會使用成員資格數據庫。兩個鏈接字符串之間的惟一區別是數據庫名稱和名稱屬性值。
當你第一次開始開發應用程序時,您的數據模型更改頻繁,並且每次獲取與數據庫不一樣步的模型更改。您能夠配置實體框架能夠自動刪除並從新建立該數據庫的每次更改數據模型。這不是一個問題在開發的早期,由於測試數據是很容易從新建立,可是您已經部署到生產後你一般想要更新數據庫架構,而不刪除數據庫。遷移功能使代碼第一要更新數據庫,而不會刪除並從新建立它。早在開發週期中的一個新的項目你可能想要使用DropCreateDatabaseIfModelChanges ,能夠刪除、 從新建立和從新設置爲種子數據庫每次模型更改。一我的,你準備部署您的應用程序,您能夠轉換爲的遷移方法。在本教程中,您將僅使用遷移。有關的詳細信息,請參見代碼第一次遷移和遷移截屏視頻系列.
從工具菜單上,單擊庫程序包管理器,而後程序包管理器控制檯.
在PM>
提示符下輸入如下命令:
enable-migrations -contexttypename SchoolContext
此命令在 ContosoUniversity 項目中,建立一個遷移文件夾和它在該文件夾中放一個Configuration.cs文件,您能夠編輯配置遷移。
Configuration
類包括建立數據庫時,每次更新數據模型更改後調用的Seed
方法。
internal sealed class Configuration : DbMigrationsConfiguration<ContosoUniversity.Models.SchoolContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(ContosoUniversity.Models.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" } // ); // } }
這Seed
方法的目的是使您可以向數據庫中插入測試數據後代碼第一次建立或更新它。
種子方法運行時代碼第一次遷移建立數據庫和每一次它將更新到最新的遷移數據庫。種子法的目的是爲了使您可以將數據插入到表以前應用程序訪問數據庫第一次。
在早期版本的代碼優先,遷移被釋放以前,它是日常的Seed
方法來插入測試數據,由於在開發過程當中的每一個模型修改數據庫不得不被徹底刪除和從新建立從零開始。與代碼第一次遷移,測試數據保留後數據庫更改,所以包括種子方法中的測試數據一般不是必需。事實上,你不想要插入測試數據,若是您將使用遷移將數據庫部署到生產,由於Seed
方法將運行在生產中的Seed
方法。在這種狀況下你但願Seed
方法向數據庫中插入你想要在生產中插入的數據。例如,您可能想要包括實際部門名稱Department
表中,當應用程序在生產中可用的數據庫。
對於本教程,您將使用遷移的部署,但你的Seed
方法將插入測試數據不管如何爲了使它更加輕鬆地查看應用程序的功能而無需手動插入大量的數據的工做。
namespace ContosoUniversity.Migrations { using System; using System.Collections.Generic; 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) { 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") },