前言
Contoso 大學示例 Web 應用程序演示如何使用實體框架(EF)Core 2.0 和 Visual Studio 2017 創(chuàng)建 ASP.NET Core 2.0 MVC Web 應用程序箕戳。
示例應用程序是虛構(gòu)的Contoso大學的網(wǎng)站啰脚。 它包括學生入學轨功,課程創(chuàng)建和教師任務(wù)等功能。 這是一系列教程中的第一章志鞍,介紹如何從頭構(gòu)建Contoso大學示例應用程序校翔。
下載或查看已完成的應用程序 - 官方。
EF Core 2.0 是EF的最新版本,但還沒有包括所有的 EF 6.x 功能枣宫。 有關(guān) EF 6.x 和 EF Core 之間如何選擇的信息,請參閱 EF Core vs. EF6.x吃环。 如果您選擇 EF 6.x 也颤,請參閱本教程系列的以前版本。
注意事項
- 對于本教程的 ASP.NET Core 1.1 版本郁轻,請參閱PDF格式的本教程的 VS 2017 Update 2版本翅娶。
- 對于本教程的 Visual Studio 2015 版本,請參閱PDF格式的 VS 2015 版本的 ASP.NET Core 文檔好唯。
開發(fā)環(huán)境
安裝如下工具:
- .NET Core 2.0.0 SDK 或更新版本竭沫。
- Visual Studio 2017 V15.3 或更高版本,安裝 ASP.NET 和 Web 開發(fā)工具骑篙。
故障排除
如果遇到問題蜕提,您無法解決,通嘲卸耍可以通過將代碼與完成的項目進行比較來找到解決方案谎势。 有關(guān)常見錯誤和解決方法的列表,請參閱本系列最后一個教程的故障排除部分杨名。 如果您沒有找到所需的內(nèi)容脏榆,您也可以在 StackOverflow.com 上提問。
小貼士
本系列包含10個教程台谍,每個教程都建立在早期教程中的基礎(chǔ)之上姐霍。 在成功完成每個教程之后,請考慮保存項目的副本。 然后镊折,如果遇到問題,您可以從上一個教程重新開始介衔,無需從頭開始恨胚。
Contoso 大學網(wǎng)站應用
教程中構(gòu)建的是一個簡單的大學網(wǎng)站。
用戶可以查看和更新學生炎咖,課程和教師信息赃泡。 下面是您將要創(chuàng)建的一些頁面。
網(wǎng)站的 UI 風格與內(nèi)置模板生成的 UI 風格保持一致乘盼,本教程主要關(guān)注如何使用 Entity Framework升熊。
創(chuàng)建 ASP.NET Core MVC 網(wǎng)站應用
打開 Visual Studio 并創(chuàng)建名為 “ContosoUniversity” 的新 ASP.NET Core C# web 項目。
- 從文件菜單中绸栅,選擇新建>項目级野。
- 從左窗格中選擇 已安裝 -> Visual C# -> Web 。
- 中間窗格選擇 ASP.NET Core Web 應用程序粹胯。
-
輸入 ContosoUniversity 作為項目名稱,然后單擊確定。
- 等待 "新建 ASP.NET Core Web 應用程序" 對話框出現(xiàn)
- 選擇 ASP.NET Core 2.0 和 Web應用程序(模型視圖控制器)模板殷勘。
- 注意:本教程需要 ASP.NET Core 2.0 和 EF Core 2.0 或更高版本 - 確保未選擇ASP.NET Core 1.1薄风。
- 確保認證設(shè)置為“不進行身份驗證”。
- 單擊 “確定” 按鈕竹观。
設(shè)置網(wǎng)站樣式
簡單修改幾個位置镐捧,設(shè)置站點菜單,布局和主頁臭增。
打開 Views/Shared/_Layout.cshtml 文件懂酱,進行以下更改:
- 將三處 “ContosoUniversity” 文字修改為“Contoso University”。
- 添加 學生速址、課程玩焰、教師和部門菜單,刪除聯(lián)系人菜單芍锚。
主要的修改如下
<html>
......
<title>@ViewData["Title"] - Contoso University</title>
......
class="navbar-brand">Contoso University</a>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
<li><a asp-area="" asp-controller="Home" asp-action="About">About</a></li>
<li><a asp-area="" asp-controller="Students" asp-action="Index">Students</a></li>
<li><a asp-area="" asp-controller="Courses" asp-action="Index">Courses</a></li>
<li><a asp-area="" asp-controller="Instructors" asp-action="Index">Instructors</a></li>
<li><a asp-area="" asp-controller="Departments" asp-action="Index">Departments</a></li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>? 2017 - Contoso University</p>
</footer>
</div>
</body>
</html>
在 Views/Home/Index.cshtml 文件昔园,使用以下代碼替換文件的內(nèi)容:
@{
ViewData["Title"] = "Home Page";
}
<div class="jumbotron">
<h1>Contoso University</h1>
</div>
<div class="row">
<div class="col-md-4">
<h2>Welcome to Contoso University</h2>
<p>
Contoso University is a sample application that
demonstrates how to use Entity Framework Core in an
ASP.NET Core MVC web application.
</p>
</div>
<div class="col-md-4">
<h2>Build it from scratch</h2>
<p>You can build the application by following the steps in a series of tutorials.</p>
<p><a class="btn btn-default" >See the tutorial ?</a></p>
</div>
<div class="col-md-4">
<h2>Download it</h2>
<p>You can download the completed project from GitHub.</p>
<p><a class="btn btn-default" >See project source code ?</a></p>
</div>
</div>
按 CTRL+F5 運行項目或從菜單中選擇 調(diào)試-> 開始執(zhí)行(不調(diào)試), 您將在瀏覽器中看到本教程中實現(xiàn)的首頁并炮。
Entity Framework Core NuGet packages
譯者注: 此標題不翻譯好過翻譯
要在項目中添加 EF Core 支持默刚,需要安裝相應的數(shù)據(jù)庫實現(xiàn)。本教程使用 SQL Server 數(shù)據(jù)庫逃魄,所需要的程序包 Microsoft.EntityFrameworkCore.SqlServer 已經(jīng)內(nèi)置于 Microsoft.AspNetCore.All 包中荤西,因此我們現(xiàn)在什么都不必做。
這個程序包 (Microsoft.EntityFrameworkCore) 及其依賴項 (Microsoft.EntityFrameworkCore.Relational) 提供了EF運行時支持。在稍后的 ”數(shù)據(jù)庫遷移“教程中邪锌,你將會學習添加一個工具包勉躺。
有關(guān)可用于 Entity Framework Core 的其他數(shù)據(jù)庫支持程序的信息,請參閱 Data Providers觅丰。
創(chuàng)建數(shù)據(jù)模型
接下來饵溅,您將為Contoso大學應用程序創(chuàng)建實體課程。 您將從以下三個實體開始妇萄。
在 Student 與 Enrollement 實體間是一個一對多的關(guān)系蜕企, 在 Course 與 Enrollment 間也存在一對多關(guān)系。 換句話說冠句,學生可以參加任意數(shù)量的課程轻掩,課程可以有任意數(shù)量的學生注冊。
在以下部分中懦底,您將為每個實體創(chuàng)建一個類唇牧。
Student 實體
在 Models 文件夾中,創(chuàng)建一個名為 Student.cs 的類文件基茵,并使用以下代碼替換模板代碼奋构。
using System;
using System.Collections.Generic;
namespace ContosoUniversity.Models
{
public class Student
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
}
}
ID
屬性將成為對應數(shù)據(jù)表的主鍵。默認情況下拱层,Entity Framework 將名為 ID 或 {類名}ID 的屬性解釋為主鍵弥臼。
Enrollments
屬性是導航屬性。導航屬性用于關(guān)聯(lián)其他實體根灯。對于一個學生實體(數(shù)據(jù))來說径缅,其中的 Enrollments 屬性包含所有與該學生相關(guān)聯(lián)的 Enrollment 實體(數(shù)據(jù))。也就是說烙肺,如果數(shù)據(jù)庫中的一個學生行數(shù)據(jù)關(guān)聯(lián)兩個注冊行數(shù)據(jù)(一對多纳猪,在 Enrollment 表中外鍵關(guān)聯(lián)StudentID 值為該學生的主鍵值),則 Student 實體中的 Enrollments 導航屬性將包含這兩個 Enrollment 實體桃笙。
如果導航屬性可以容納多個實體(在多對多或一對多關(guān)系中)氏堤,則其類型必須是可以添加,刪除和更新條目的列表搏明,例如ICollection <T>鼠锈。您可以指定ICollection <T>或類型,如List <T>或HashSet <T>星著。如果指定ICollection <T>购笆,EF默認創(chuàng)建一個HashSet <T>集合。
Enrollment 實體
在 Models 文件夾中虚循,創(chuàng)建一個名為 Student.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 Course Course { get; set; }
public Student Student { get; set; }
}
}
EnrollmentID
屬性將成為主鍵。本實體使用 {類名}ID 模式代替在 Studnet 實體中使用的 ID 模式铺遂。 通常你會只選擇一種模式衫哥,并在整個數(shù)據(jù)模型中使用。 在這里娃循,不同的模式是為了演示炕檩,說明您可以使用任一模式。 在后面的教程中捌斧,您將看到如何使用沒有類名的 ID 可以更容易地在數(shù)據(jù)模型中實現(xiàn)繼承。
Grade (等級)
屬性是一個枚舉類型泉沾。 Grade
類型聲明后的 ?
表示 可為空類型捞蚂。 一個空的等級和一個值為0的等級是不同的 -- 空表示等級未知或者尚未被賦值。
StudentID
屬性是外鍵跷究,相應的導航屬性是 Student
姓迅。 一個 Enrollment
實體與一個 Student
實體相關(guān)聯(lián),因此該屬性只能持有保存單個 Studnet
實體(與您之前看到的可以包含多個注冊實體的 Student.Enrollments
導航屬性不同)俊马。
CourseID
屬性是外鍵, 對應的導航屬性是 Course
丁存。 一個 Enrollment
實體與一個 Course
實體相關(guān)聯(lián)。
當一個屬性名稱符合模式 <導航屬性名><主鍵名> , EF 將屬性解析為外鍵屬性(例如柴我,StudentID
對應 Student
導航屬性解寝,因為 Student
實體的主鍵是 ID
)。 外鍵屬性也可以簡單地使用 <主鍵屬性名稱>(例如艘儒,CourseID
聋伦,因為課程實體的主鍵是 CourseID
)。
Course 實體
在 Models 文件夾中界睁,創(chuàng)建一個名為 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 ICollection<Enrollment> Enrollments { get; set; }
}
}
Enrollments
屬性是導航屬性翻斟。一個 Course
實體可以關(guān)聯(lián)到任意多個 Enrollment
實體逾礁。
我們將在本系列的后續(xù)教程中詳細介紹 DatabaseGenerated
特性。 此特性允許您指定 Course
的主鍵名访惜,而不是讓數(shù)據(jù)庫生成它嘹履。
創(chuàng)建數(shù)據(jù)庫上下文 Database Context
將數(shù)據(jù)模型與 Entity Framework 功能協(xié)同工作的主要類是數(shù)據(jù)庫上下文類。 通過從 Microsoft.EntityFrameworkCore.DbContext 類派生來創(chuàng)建此類疾牲。 在代碼中植捎,可以指定數(shù)據(jù)模型中包含哪些實體。 還可以自定義某些 Entity Framework 行為阳柔。 在這個項目中焰枢,該類被命名為 SchoolContext
。
在項目文件夾中,創(chuàng)建一個名為Data的文件夾济锄。
在 Data 文件夾中創(chuàng)建一個名為 SchoolContext.cs 的新類暑椰,并用以下代碼替換模板代碼:
using ContosoUniversity.Models;
using Microsoft.EntityFrameworkCore;
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
}
}
應用數(shù)據(jù)上下文 - 使用依賴注入
ASP.NET Core 默認使用依賴注入技術(shù)。 服務(wù)(如EF數(shù)據(jù)庫上下文)在應用程序啟動期間通過依賴注入注冊實例荐绝。 那些需要使用服務(wù)的組件通過構(gòu)造函數(shù)參數(shù)獲得服務(wù)的實例一汽。 稍后我們可以看到控制器構(gòu)造函數(shù)獲取上下文實例的代碼。
要將 SchoolContext
注冊為服務(wù)低滩,請打開 Startup.cs
召夹,并按照如下代碼修改 ConfigureServices
方法。
//Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
}
通過調(diào)用 DbContextOptionsBuilder 對象上的方法將連接字符串的名稱傳遞給上下文恕沫。 對于本地開發(fā)监憎,ASP.NET Core 配置系統(tǒng)從 appsettings.json 文件讀取連接字符串。
打開appsettings.json文件并添加一個連接字符串婶溯,如下例所示鲸阔。
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=ContosoUniversity1;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"IncludeScopes": false,
"LogLevel": {
"Default": "Warning"
}
}
}
SQL Server Express LocalDB
連接字符串指定 SQL Server LocalDB 數(shù)據(jù)庫。 LocalDB 是 SQL Server Express 數(shù)據(jù)庫引擎的輕量級版本迄委,旨在用于應用程序開發(fā)褐筛,而不是生產(chǎn)用途。 LocalDB 按需啟動并以用戶模式運行叙身,因此沒有復雜的配置渔扎。 默認情況下,LocalDB在 C:/Users/<user> 目錄中創(chuàng)建 .mdf 數(shù)據(jù)庫文件曲梗。
添加代碼赞警,使用測試數(shù)據(jù)初始化數(shù)據(jù)庫
EF 將為您創(chuàng)建一個空數(shù)據(jù)庫。 在本節(jié)中虏两,您將編寫一個創(chuàng)建數(shù)據(jù)庫后調(diào)用的方法愧旦,以便使用測試數(shù)據(jù)進行填充。
在這里定罢,您將使用 EnsureCreated 方法自動創(chuàng)建數(shù)據(jù)庫笤虫。 在后面的教程中,您將看到如何使用 Code First Migration
(代碼優(yōu)先遷移) 來更改數(shù)據(jù)庫架構(gòu)而不是刪除和重新創(chuàng)建數(shù)據(jù)庫來處理架構(gòu)更改祖凫。
在 Data
文件夾中琼蚯,創(chuàng)建一個名為 DbInitializer.cs 的新類文件,并使用以下代碼替換模板代碼惠况,這些代碼將在需要時創(chuàng)建數(shù)據(jù)庫遭庶,并將測試數(shù)據(jù)加載到新數(shù)據(jù)庫中。
//DbInitializer.cs
using ContosoUniversity.Models;
using System;
using System.Linq;
namespace ContosoUniversity.Data
{
public static class DbInitializer
{
public static void Initialize(SchoolContext context)
{
context.Database.EnsureCreated();
// Look for any students.
if (context.Students.Any())
{
return; // DB has been seeded
}
var students = new Student[]
{
new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
};
foreach (Student s in students)
{
context.Students.Add(s);
}
context.SaveChanges();
var courses = new 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}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();
var enrollments = new Enrollment[]
{
new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
new Enrollment{StudentID=3,CourseID=1050},
new Enrollment{StudentID=4,CourseID=1050},
new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
new Enrollment{StudentID=6,CourseID=1045},
new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
};
foreach (Enrollment e in enrollments)
{
context.Enrollments.Add(e);
}
context.SaveChanges();
}
}
}
代碼檢查數(shù)據(jù)庫中是否有學生稠屠,如果沒有峦睡,則假定數(shù)據(jù)庫是新的翎苫,并且需要使用測試數(shù)據(jù)進行種子。它將測試數(shù)據(jù)加載到數(shù)組而不是 List <T> 集合來優(yōu)化性能榨了。
在Program.cs中煎谍,修改Main方法在應用程序啟動時執(zhí)行以下操作:
- 從依賴注入容器獲取數(shù)據(jù)庫上下文實例。
- 調(diào)用種子方法龙屉,傳遞給它的上下文呐粘。
- 種子方法完成時銷毀上下文。
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<SchoolContext>();
DbInitializer.Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
在較舊的教程中转捕,您可能會在Startup.cs中的Configure方法中看到類似的代碼作岖。 我們建議您僅使用Configure方法來設(shè)置請求管道。 應用程序啟動代碼屬于Main方法五芝。
首次運行應用程序時鳍咱,將創(chuàng)建數(shù)據(jù)庫并植入測試數(shù)據(jù)。 無論何時更改數(shù)據(jù)模型与柑,都可以刪除數(shù)據(jù)庫,更新種子方法蓄坏,并以新的數(shù)據(jù)庫重新開始重新啟動价捧。 在后面的教程中,您將看到在數(shù)據(jù)模型更改時如何修改數(shù)據(jù)庫涡戳,而不刪除和重新創(chuàng)建它结蟋。
創(chuàng)建控制器和視圖
接下來,您將使用 Visual Studio 腳手架添加 MVC 控制器和視圖渔彰,并使用 EF 來查詢和保存數(shù)據(jù)嵌屎。
自動創(chuàng)建CRUD操作方法和視圖稱為腳手架。 腳手架與代碼生成器不同之處在于恍涂,腳手架代碼只是基礎(chǔ)代碼宝惰,您可以根據(jù)自己的需要進行修改,而通常情況下再沧,您不會修改生成器生成的代碼尼夺。 當您需要自定義生成器生成的代碼,可以使用部分類炒瘸,或者在情況發(fā)生改變時時重新生成代碼淤堵。
- 右鍵單擊解決方案資源管理器中的 Controllers 文件夾,然后選擇 添加 -> 控制器顷扩。
- 在“添加基架”對話框中拐邪,選擇“視圖使用 Entity Framework 的 MVC 控制器”,點擊“添加”
- 在“添加控制器”對話框中:
- 模型類選擇
Student
隘截。 - 數(shù)據(jù)上下文類選擇
SchoolContext
- 點擊 “添加”扎阶。
- 模型類選擇
當您單擊添加時汹胃,Visual Studio 腳手架引擎創(chuàng)建一個 StudentsController.cs 文件和一組與控制器一起使用的視圖(.cshtml文件)。
(腳手架引擎還可以為您創(chuàng)建數(shù)據(jù)庫上下文乘陪,如果您不像以前在本教程中那樣手動創(chuàng)建它统台。 您可以通過單擊數(shù)據(jù)上下文類右側(cè)的加號在“添加控制器”框中指定新的上下文類。 然后Visual Studio將創(chuàng)建您的DbContext類以及控制器和視圖啡邑。)
你會注意到控制器將一個 SchoolContext 作為一個構(gòu)造函數(shù)參數(shù)贱勃。
namespace ContosoUniversity.Controllers
{
public class StudentsController : Controller
{
private readonly SchoolContext _context;
public StudentsController(SchoolContext context)
{
_context = context;
}
ASP.NET 依賴注入負責將 SchoolContext 的一個實例傳遞到控制器中。 前文中谤逼,已經(jīng)
在 Startup.cs 文件中配置 SchoolContext 的依賴注入贵扰。
控制器包含一個 Index
方法,用于顯示數(shù)據(jù)庫中的所有學生流部。 該方法通過讀取數(shù)據(jù)庫上下文實例的 Students
屬性獲取學生實體集中的學生列表:
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
稍后將介紹此代碼中的異步編程知識戚绕。
視圖 Views/Students/Index.cshtml 使用 HTML 表格顯示學生列表。 (此處未對腳手架生成的代碼進行任何修改枝冀,不再貼代碼占用文章篇幅舞丛。 )
按 CTRL + F5 運行項目或從菜單中選擇 調(diào)試 -> 開始執(zhí)行(不調(diào)試)。
單擊 Student
鏈接果漾,可以看到 DbInitializer.Initialize 方法中插入的測試數(shù)據(jù)球切。 根據(jù)瀏覽器窗口的狹窄程度,您會看到頁面頂部的 Student
鏈接绒障,也有可能您必須單擊右上角的導航圖標才能看到隱藏菜單中的鏈接吨凑。
查看數(shù)據(jù)庫
當您啟動應用程序時,DbInitializer.Initialize 方法調(diào)用 EnsureCreated 户辱。 EF 看到?jīng)]有數(shù)據(jù)庫鸵钝,所以它創(chuàng)建了一個,然后 Initialize 方法代碼的其余部分用數(shù)據(jù)填充數(shù)據(jù)庫庐镐。 在 Visual Studio 中恩商,您可以使用 SQL Server 對象資源管理器(SSOX)查看數(shù)據(jù)庫。
如果 SSOX 窗口尚未打開焚鹊,在 Visual Studio 中痕届,點擊菜單 “視圖” -> “SQL Server 對象資源管理器”。
在 SSOX 中末患,單擊(localdb)\ MSSQLLocalDB > 數(shù)據(jù)庫研叫,然后單擊 ContosoUniversity1,也就是我們前面在 appsettings.json 文件中設(shè)置的連接字符串中數(shù)據(jù)庫名稱璧针。
展開“表”節(jié)點以查看數(shù)據(jù)庫中的表嚷炉。
右鍵單擊 Student
表,然后單擊 “查看數(shù)據(jù)” 以查看已創(chuàng)建的列和插入到表中的數(shù)據(jù)行探橱。
.mdf 和.ldf 數(shù)據(jù)庫文件位于C:\Users<你的用戶名> 文件夾中申屹。
因為您在應用程序啟動時運行的初始化程序方法中調(diào)用 EnsureCreated 绘证,所以現(xiàn)在可以更改 Student 類,刪除數(shù)據(jù)庫哗讥,再次運行應用程序嚷那,并自動重新創(chuàng)建數(shù)據(jù)庫以匹配您的更改。 例如杆煞,如果您將 EmailAddress 屬性添加到 Student 類魏宽,則會在重新創(chuàng)建的表中看到一個新的EmailAddress 列。
約定
基于約定優(yōu)于配置的原則决乎,Entity Framework 構(gòu)建一個數(shù)據(jù)庫時队询,你所需書寫的代碼很少。
DbSet 屬性的名稱用作表名构诚。 對于未由DbSet屬性引用的實體蚌斩,實體類名用作表名。
實體屬性名稱用于列名范嘱。
名為 ID 或 classnameID 的實體屬性被識別為主鍵屬性送膳。
使用 導航屬性名+實體主鍵名 命名的屬性,會被自動識別為外鍵丑蛤,例如: StudentID 由 Student (導航屬性) + ID (Student實體主鍵名 )組成肠缨。外鍵也可以簡單只使用實體主鍵名,例如 EnrollmentID (外鍵) 與 EnrollmentID (Enrollment 實體的主鍵)盏阶。
約定可以被覆蓋。例如闻书,你可以顯式指定表名名斟,如本教程前面所看到的。 您可以設(shè)置列名稱并將任何屬性設(shè)置為主鍵或外鍵魄眉,這將在后面的教程中提及砰盐。
異步代碼
ASP.NET Core和EF Core的默認使用異步編程。
Web 服務(wù)器的可用線程數(shù)量有限坑律,在高負載情況下岩梳,所有可用線程都可能都在使用。 當發(fā)生這種情況時晃择,服務(wù)器無法處理新的請求冀值,直到線程被釋放。 使用同步代碼時宫屠,許多線程可能會被綁定列疗,而實際上它們并沒有做任何工作,因為它們正在等待 I/O 完成浪蹂。 使用異步代碼抵栈,當進程正在等待I/O 完成時告材,其線程將被釋放,供服務(wù)器用于處理其他請求古劲。 因此斥赋,異步代碼可以更有效地使用服務(wù)器資源,并且使服務(wù)器能夠無延遲地處理更多流量产艾。
異步代碼在運行時引入了少量的開銷疤剑,但是對于低流量情況,性能下降可以忽略不計胰舆,而對于高流量情況骚露,潛在的性能提升是巨大的。
在以下代碼中缚窿,async 關(guān)鍵字棘幸, Task<T> 返回值,await 關(guān)鍵字和 ToListAsync 方法共同構(gòu)成異步執(zhí)行代碼倦零。
public async Task<IActionResult> Index()
{
return View(await _context.Students.ToListAsync());
}
async
關(guān)鍵字告訴編譯器為方法體生成回調(diào)函數(shù)误续,并自動創(chuàng)建返回的Task <IActionResult>
對象。返回類型
Task<IActionResult>
表示正在進行的工作扫茅,其結(jié)果類型為IActionResult
蹋嵌。await
關(guān)鍵字告訴編譯器將該方法分為兩部分。 第一部分以異步啟動的操作結(jié)束葫隙。 第二部分被放入回調(diào)方法栽烂,該操作在操作完成時被調(diào)用。ToListAsync
是ToList
擴展方法的異步版本恋脚。
當您編寫使用實體框架的異步代碼時腺办,需要注意的一些事情:
只有會引發(fā)查詢或?qū)⒚畎l(fā)送到數(shù)據(jù)庫的語句才需要異步執(zhí)行。 這包括例如
ToListAsync
糟描,SingleOrDefaultAsync
和SaveChangesAsync
怀喉。 它不應該包括,例如船响,只是更改IQueryable的語句躬拢,類似var students = context.Students.Where(s => s.LastName == "Davolio")
這樣的語句。EF上下文不是線程安全的:不要嘗試并行執(zhí)行多個操作见间。 當您調(diào)用任何異步 EF 方法時聊闯,請始終使用 await 關(guān)鍵字。
如果您想利用異步代碼的性能優(yōu)勢米诉,請確保您正在使用的任何庫包(例如用于分頁)也使用異步馅袁,如果他們調(diào)用任何導致查詢發(fā)送到數(shù)據(jù)庫的方法。
有關(guān).NET中異步編程的更多信息荒辕,請參閱 Async Overview汗销。
小結(jié)
您現(xiàn)在創(chuàng)建了一個簡單的應用程序犹褒,使用 Entity Framework Core 和 SQL Server Express LocalDB 存儲和顯示數(shù)據(jù)。 在下面的教程中弛针,您將學習如何執(zhí)行基本的 CRUD(創(chuàng)建叠骑,讀取,更新和刪除)操作削茁。