1. 程式人生 > >NET Core & Entity Framework Core

NET Core & Entity Framework Core

uget docs f11 自動生成 腳本 字符 obj 數據庫操作 eba

本文是ABP官方文檔翻譯版,翻譯基於 3.2.5 版本

官方文檔分四部分

一、 教程文檔

二、ABP 框架

三、zero 模塊

四、其他(中文翻譯資源)

本篇是第一部分的第一篇。

第一部分分三篇

1-1 手把手引進門

1-2 進階

1-3 雜項 (相關理論知識)

第一篇含兩個步驟。

1-1-1 ASP.NET Core & Entity Framework Core 後端(內核)含兩篇 (第二篇鏈接)

1-1-2 ASP.NET MVC, Web API, EntityFramework & AngularJs 前端

現在進入正文

使用 ASP.NET Core, Entity Framework Core 和 ASP.NET Boilerplate 創建N層Web應用

土牛語錄:Halil ibrahim Kalkan, 30 Jul 2017

以下是手把手引進門教程,基於 ASP.NET Core, Entity Framework Core ,ABP 框架 創建Web 應用, PS: 自帶自動的測試模塊哦。

  • 樣例下載 (上 github 的請自便)

本文目錄如下:

介紹

  前期準備

創建應用

正式開發

  創建任務實體 Entity

  將任務添加到數據庫上下文 DbContext

  創建第一個數據遷移

  創建數據庫

  編寫任務服務

  測試任務服務

  任務列表展示

    添加菜單

    創建任務 Controller 和 視圖模型

    任務列表頁面

    本地化

    任務過濾

    任務列表頁面的自動化測試

其他相關內容

文章修改歷史

版權所有

介紹

這是系列文章的第一部分:使用 ASP.NET Core, Entity Framework Core 和 ASP.NET Boilerplate 創建N層Web應用

在本文中,我將指導大家創建一個樣例(跨平臺的多層Web應用),該樣例會用到如下工具(請讀者提前準備):

  • Net Core 跨平臺應用的基礎開發框架
  • ASP.NET Boilerplate (ABP) 開發的基礎框架模板
  • ASP.NET Core web開發框架
  • Entity Framework Core ORM 數據框架
  • Twitter Bootstrap HTML&CSS 前端開發框架
  • jQuery 客戶端 AJAX/DOM 類庫
  • xUnit 和 Shouldly 服務端測試工具(單元測試/集成測試)

ABP 框架中會默認使用 Log4Net 和 AutoMapper 。

我們同時還會使用以下技術:

  • Layered Architecture 分層架構
  • Domain Driven Design (DDD) DDD領域模型
  • Dependency injection (DI) DI 依賴註入
  • Integration Testing 集成測試

演示的開發項目是一個簡單的任務管理應用,用於將任務分配出去。我不會一層一層的進行開發,而是隨著應用的拓展直接切換所需的層次。隨著應用的推拓展,我將會介紹所需的ABP和其他框架的特性。

前期準備

開發樣例時需要以下工具,請提前在你的機器上進行安裝:

  • Visual Studio 2017
  • SQL Server (你可以更改連接字符串為 localdb)
  • Visual Studio Extensions:
    • Bundler & Minifier
    • Web Compiler

創建應用

首先使用ABP模版(http://www.aspnetboilerplate.com/Templates)創建一個web應用項目,命名為"Acme.SimpleTaskApp" 。創建模板時可以設置自己的公司名稱(比如Acme)。

本樣例使用MPA(Multi Page Web Application)多頁面模式(註:即使用MVC和Razor技術)進行開發,本文不使用SPA(註:土牛的SPA是使用Angular)單頁面模式。同時為了使用最基礎的開發模板功能,本文不使用Module Zero模塊。

技術分享圖片

ABP 模版會創建一個多層的解決方案,如下圖:

技術分享圖片

模板會根據輸入的名字自動創建6個項目。

  • core 領域層/業務層,包含實體Entity,領域服務 domain service 等等
  • Application 應用層 , 包含DTO,應用服務 application service 等等
  • Entity Framework 基礎設施層 ,EF core 數據庫集成處理 (從其他層抽象出來的EF core)
  • Web 展示層 , 即Asp.net MVC層
  • Tests 單元測試和集成測試,含應用層,領域層,基礎設施層,不含Web展示層
  • Web.Tests ASP.NET Core集成測試,包含web展示層的全部集成測試

以上是沒有選擇zero的項目結果,如果你選擇了zero,項目結構就會變成下圖:

技術分享圖片

當你把應用運行起來後,你會看到下圖所示的用戶界面:

技術分享圖片

這個應用包含一個頂級菜單欄,包含空的首頁,關於頁,還有一個語言的下拉選項。

正式開發

創建任務實體 Entity

我們從創建一個簡單的任務實體 Task Entity 開始,由於它屬於領域層,把它加到 core 項目裏。

代碼如下:

技術分享圖片 View Code

  • Task 實體從 ABP 的 Entity 基類繼承,Entity 基類默認ID屬性是 int 類型。如果主鍵類型為非 int 類型,也可以選擇範型版本的 Entity<TPrimaryKey>.
  • IHasCreationTime 是一個簡單的接口,只定義了 CreationTime 屬性 (統一規範 CreationTime 的名字)
  • Task 實體定義了一個必填的 Title 和 非必填的 Description
  • TaskState 是一個簡單枚舉,定義了 Task 任務的狀態
  • Clock.Now 返回默認的 DateTime.Now 。但它提供了一個抽象方法,使得我們可以在將來有需要的時候很輕松就可以轉換為 DateTime.UtcNow 。在 ABP 框架中總是使用Clock.Now 而不使用 DateTime.Now 。
  • 將 Task 實體存儲到數據庫的 AppTasks 表中。

將任務添加到數據庫上下文 DbContext

.EntityFrameworkCore 包含一個預定義的 DbContext 。將 Task 實體的 DbSet 加到 DbContext 裏。

代碼如下:

技術分享圖片 View Code

現在,EF core 知道我們有了一個 Task 的實體。

創建第一個數據遷移

我們將創建一個初始化數據庫遷移文件,它會自動創建數據庫和數據庫表 AppTasks 。打開源管理器 Package Manager Console from Visual Studio , 執行 Add-Migration 命令(默認的項目必須是 .EntityFrameworkCore 項目),如圖:

技術分享圖片

這個命令會在 . EntityFrameworkCore 項目下創建一個遷移( Migrations )文件夾,文件夾包含一個遷移類和數據庫模型的快照,如圖:

技術分享圖片

如下代碼所示,自動創建了 “初始化 ( Initial )”遷移類:

技術分享圖片 View Code

當我們執行數據庫遷移命令時,這些代碼會創建 AppTasks 表 (更多遷移相關信息請參照 entity framework documentation )

創建數據庫

以上的遷移執行完畢後(註:Add-Migration 命令執行後),在包管理控制臺中執行 Update-Database 命令,如下圖:

技術分享圖片

這個命令將在 local SQL Server 中創建一個名為 “SimpleTaskAppDb” 的數據庫並執行數據庫遷移(此時,我們只有一個“初始化 ( Initial )”的遷移):

技術分享圖片

現在,我們有了 Task 實體,並且在數據庫中有對應的數據庫表, 我們輸入一些簡單的任務到表裏。

技術分享圖片

友情提示: 數據庫上下文字符串 connection string 在 .web 應用的 appsettings.json 中。 (要換數據庫的自己改一下字符串哦)。

編寫任務服務

Application Services 應用層服務用於將領域業務邏輯暴露給展示層。展示層在必要時通過使用 Data Transfer Object 數據傳輸對象(DTO)作用參數調用一個應用服務,應用服務則通過調用領域對象執行一些具體的業務邏輯並在有需要時返回一個DTO給展示層。

我們在 .Application 項目中創建第一個應用服務 TaskAppService ,該服務將執行與任務相關的應用程序邏輯。首先,我們先來定義一個app 服務接口:

代碼如下:

技術分享圖片 View Code

我們推薦先定義接口,但不是非這樣做不可。按照慣例,ABP 中所有的應用服務都需要實現 IApplicationService 接口 (它只是一個空的標記接口)。我們創建了一個 GetAll 方法去查詢任務列表,同時,我們定義了如下的 DTOs :

代碼如下:

技術分享圖片 View Code
  • GetAllTasksInput DTO 為 GetAll 應用服務方法定義了一個輸入參數 。 我們將 狀態 state 定義為 DTO 對象 而不定義為方法的參數。 這樣我們將來需要的時候可以在這個DTO增加其他的參數,同時兼容現有的客戶端 (當然我們也可以在方法裏加一個 state 參數)。
  • TaskListDto 用開返回任務數據。該Dto 從 EntityDto 繼承,EntityDto 只是定義了 Id 屬性(我們可以不繼承 EntityDto ,直接自己將 Id 加到我們的Dto裏)。我們定義了[AutoMapFrom] 特性來創建 AutoMapper 自動映射任務實體到任務列表Dto TaskListDto 。這個特性在 Abp.AutoMapper nuget 包裏進行了定義。
  • ListResultDto 是一個簡單的類,包含了一個列表(我們可以直接返回一個 List<TaskListDto> 列表)。

現在,我們可以實現 ITaskAppService 了。

代碼如下:

技術分享圖片 View Code

  • TaskAppService 該類從 SimpleTaskAppAppServiceBase 繼承,SimpleTaskAppAppServiceBase (從 ABP 的 ApplicationService 類繼承)在模板裏已經自動生成。 TaskAppService 不是必須從 SimpleTaskAppAppServiceBase 繼承,應用服務可以是普通類。但是 ApplicationService 基類有一些預先註入的服務(就像這裏使用的 ObjectMapper )
  • 我們使用依賴註入 dependency injection 來獲取數據倉儲 repository
  • Repositories 數據倉儲用於為數據實體抽象數據庫操作。ABP 為每個實體創建了預定義的數據庫倉儲(就像這裏用到了 IRepository<Task> )用於實現通用的任務。IRepository.GetAll() 方法用於查詢數據實體,它返回了一個 IQueryable 接口。
  • WhereIf 這是 ABP 裏的一個拓展方法,該方法提供了一個 IQueryable.Where 方法的簡便條件語法。
  • ObjectMapper 用於將任務對象列表映射到任務列表Dto對象列表 (基於 Application Service 基類並默認實現 AutoMapper )

測試任務服務

在創建用戶接口錢,我們需要測試一下任務應用服務 TaskAppService 。 如果你對自動化測試不感興趣的話,可以忽略這個部分。

我們的模板包含 .Tests 項目,這可以測試我們的代碼。這個項目不使用 SQL Server數據庫,而是使用EF core 的內存數據庫。所以,我們可以不用真實數據庫來進行單元測試。它為每個測試創建了單獨的數據庫。所以每個測試都是隔離的。我們需要在開始測試前使用 TestDataBuilder 類添加初始測試數據到內存數據庫裏。我修改了 TestDataBuilder 。

代碼如下:

技術分享圖片 View Code

通過樣例項目的源代碼,你可以看懂 TestDataBuilder 在哪裏用,具體怎麽用。我們添加2個任務(其中一個已經完成)到數據庫上下文 dbcontext 。我們可以假定數據庫中有2個任務,開始編寫測試用例。 第一個繼承測試用來測試 TaskAppService.GetAll 方法。

代碼如下:

技術分享圖片 View Code

我們創建2個不同的測試用例來測試 GetAll 方法。現在,我們打開測試瀏覽器(在VS主菜單的 Test\Windows\Test Explorer 菜單下)開始進行單元測試。

技術分享圖片

所有測試均成功。最後一個我們現在可以忽略它,他是一個模板生成的測試。

友情提示: ABP 模板默認安裝使用 xUnit 和 Shouldly 。我們使用它們編寫我們的測試。

任務列表展示

現在,我們確定 TaskAppService 服務可以正常工作。 我們可以開始創建頁面來展示所有的任務。

添加菜單

首先,我們在頂級菜單上添加一個新的菜單

代碼如下

技術分享圖片 View Code

模板自帶兩個頁面:首頁和關於頁,如上代碼所示。我們也可以修改它們創建新的頁面。但現在我們不修改首頁和關於頁,我們創建新的菜單項。

創建任務 Controller 和 視圖模型

我們在 .Web 項目下創建一個新的 controller 類,命名為 TasksController 。

代碼如下

技術分享圖片 View Code
  • TasksController 從 SimpleTaskAppControllerBase ( SimpleTaskAppControllerBase 從 AbpController 繼承)繼承,該類包含應用程序 Controllers 需要的通用基礎代碼。
  • 我們反射了 ITaskAppService , 以獲取到所有的任務列表。
  • 我們在 .Web 項目中創建了一個 IndexViewModel 類來將數據展示到視圖上,這樣可以不直接將 GetAll 方法的結果直接暴露到視圖上。

代碼如下

技術分享圖片 View Code

我們創建了一個簡單的視圖模型,在它的構造函數中,我們獲取了一個任務列表(由 ITaskAppService 提供)。同時它還有一個 GetTaskLabel 方法,用於在視圖中通過一個 選擇 Bootstrap 標簽來標示任務。

任務列表頁面

最後,完成實際的 Index 視圖。

代碼如下

技術分享圖片 View Code

我們使用 Bootstrap 的 list group 組件和定義好的模型來渲染視圖。我們使用 IndexViewModel.GetTaskLable() 方法來獲得任務的標簽類型。渲染後的界面如下圖:

技術分享圖片

本地化

我們在視圖裏使用 ABP 框架自帶的 L 方法。 它用於本地化語言。我們在 .Core 項目下的 Localization/Source 文件夾中定義好了本地化字符串,使用 .json 文件。英語版本的本地化語言設置

代碼如下

技術分享圖片 View Code

模板自帶了大多數的文本,當然,它們可以刪除掉。在上面的代碼中我只是加了最後的三行。使用 ABP 的本地化是相當的簡單,如果你想了解本地化系統更多的信息,請查閱文檔 localization document

任務過濾

正如之前說過的,TaskController 實際上使用的是 GetAllTasksInput ,可以靈活的過濾任務。我們可以添加一個任務列表的下拉菜單來過濾任務。首先,我們添加一個下拉菜單到視圖上(我們加到 header 裏):

代碼如下

技術分享圖片 View Code

然後我修改了 IndexViewModel , 增加了 SeletedTaskState 屬性和 GetTaskStateSelectListItems 方法:

代碼如下

技術分享圖片 View Code

我們也可以在 controller 裏設置 SelectedTaskState :

代碼如下

技術分享圖片 View Code

現在,我們運行程序,可以看到視圖的右上角有個下拉框,如圖:

技術分享圖片

我們添加了下拉框,但它現在還不能用。我們需要編寫一些簡單的 javascript 代碼,當下拉框內容更改後可以重新請求/刷新任務列表頁面。我們在 .Web 項目裏創建了 wwwroot\js\views\tasks\index.js 文件

代碼如下

技術分享圖片 View Code

我們首先添加 Bundler & Minifier 擴展程序(這是 ASP.NET Core 項目標配的壓縮文件)來壓縮腳本的大小, 然後開始在視圖裏編寫 javascript :

技術分享圖片

這將在 .Web 項目中的 bundleconfig.json 中添加以下代碼

代碼如下

技術分享圖片 View Code

同時創建了 script 的壓縮版本

技術分享圖片

無論我何時修改了index.js , index.min.js 都會自動重新生成。現在,我們可以在我們的頁面裏插入 javascript 文件了。

代碼如下

技術分享圖片 View Code

至此,我們的視圖將在開發環境下使用 index.js 包,而在生產環境中使用 index.min.js (壓縮版本)包。這是在 ASP.Net Core MVC 項目中通用的做法。

任務列表頁面的自動化測試

ASP.NET Core MVC 基礎框架中集成了一個繼承測試模塊。我們可以完整的測試我們的服務端代碼了。如果你對自動化測試不感興趣的話,你可以忽略這個部分。

ABP 模板中自帶 .Web.Tests 項目。我們創建一個普通的測試來請求 TaskController.Index , 然後檢查反饋內容:

代碼如下

技術分享圖片 View Code

GetResponseAsStringAsync 和 GetUrl 是 ABP 的 AbpAspNetCoreIntrgratedTestBase 類中很有用的方法。使用這些快捷方法我們可以比較容易的創建請求,如果直接使用客戶端請求(一個 HttpClient 的實例)會相對復雜一些。如果想深入了解,請參考 ASP.NET Core 的 integration testing documentation

當我們開始 debug 測試模塊式,我們可以看到反饋的 HTML 如下圖

技術分享圖片

上圖顯示 Index 頁面的反饋很正常。但是,我們更想知道返回的 HTML 是否正如我們所預期的那樣。 有很多類庫可以用來解析 HTML 。ABP 模板的 .Web.Tests 項目預先安裝了其中的一個類庫 AngleSharp 我們用它來檢查創建的 HTML 代碼。

代碼如下

技術分享圖片 View Code

你可以深入檢查 HTML 的更多細節。但一般來說,檢查基本的標簽就夠了。

其他相關內容

第二篇 Second article 接著開發這個應用服務。

(第二篇翻譯鏈接)

文章修改歷史

  • 2017-07-30: 將文章中的 ListResultOutput 替換為 ListResultDto
  • 2017-06-02: 將文章和解決方案修改為支持 .net core
  • 2016-08-08: 添加 第二篇 的鏈接
  • 2016-08-01: 第一次發布

版權所有

該文章和其中的任何源代碼和文件的版權均歸 The Code Project Open License (CPOL) 所有

NET Core & Entity Framework Core