2017年5月9日 星期二

[教學] ASP.NET Core MVC with Entity Framework Core (EF Core) for VS 2017

前言

Microsoft 在 Mar 7, 2017 Release了 Visual Studio 2017。剛好最近正在學習 ASP.NET Core/ EF,發現到網路上關於使用 Visual Studio 2017 實作 ASP.NET Core/ EF的教材還不是很多,於是索性自己blog一下。
這篇教學文章Step by Step介紹如何使用 Visual Studio 2017 使用 EF 建立一個ASP.NET Core MVC 的 Web Application - BookStore.

Prerequisite

教學內文


建立一個ASP.NET Core MVC 的 Web Application - BookStore

選擇.NET Core,建立 Web Application

選擇Web Application。注意,關於 Authentication 部分,如果你是選擇 "No Authentication" 的話,VS 不會幫你建立 Modules 的 Folder。原因也很簡單,Web Application by default 只能 access "wwwroot" 裡面的 data (white list),除此之外,其他都是 black list。No Authentication的話,表示目前只會 access "wwwroot" 裡面的資料,也就不需要 Models 這個 folder了。
我為了方便,選擇了 "Individual User Accounts"


針對 MVC 使用 EF 的 framework的話,EF 帶來的好處就是它幫我們很方便的建立 ORM 進而抽象調對 DB 的操作。簡單來說,就是 EF 可以幫我們 "map" domain-specific objects (model) 與 relational DB.
所以,接下來我們先來建立 model,再使用 EF 幫我們建立連結。

建立 Book.cs in Model Folder

以下為新增的BookStore.cs Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BookStore.Models
{
    public class Book
    {
        public int BookId { get; set; }
        public string Name { get; set; }
        public string PublishDate { get; set; }
    }
}

建立 Book's data context

接下來我們要為剛剛建立的 Book model 設定 data context。步驟十分的簡單,基本上三個步驟。
第一、建立一個繼承於 Microsoft.EntityFrameworkCore.DbContext 的 BooksDbContext.cs。

using BookStore.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BookStore.Data
{
    public class BooksDbContext : DbContext
    {
        public BooksDbContext(DbContextOptions optiopns) : base (optiopns)
        {

        }

        public DbSet Books { get; set; }
    }
}

第二、使用 Tool->Connect to Database 建立一個新的 DB。這裡、我使用 "Microsoft SQL Server Database File"。當然,有很多其他的 DB 選項,例如你也可以安裝 VS 2017 的 Extension 來使用 SQLite 之類的。
第三、使用 EF 的Migration Command 使用我們建立的 context data 來 update DB。先開啟 "Package Manager Console" 接著,打入以下指令:
PM> add-migration init_bookstore -Context BooksDbContext
To undo this action, use Remove-Migration.

PM> update-database -Context BooksDbContext
Done.
"add-migration" 讓 EF 幫我們產生一個 migration 的 plan : "init_bookstore"。你可以在 solution explorer 中看到產生了一個 Migrations folder。

"update-database" 則會更新 DB 了。指令完成後,我們來驗證一下。開啟 "SQL Server Object Explorer" 來檢驗我們剛剛建立的DB。

Configure MVS's services 加入 BooksDbContext

我們需要修改一下 appsettings.json 的設定,新增一個 BookStoreConnection 到 ConnectionStrings 裡面。

{
    "ConnectionStrings": {
        "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-BookStore-fd3c9b31-8627-4770-b1e6-4554bd114c57;Trusted_Connection=True;MultipleActiveResultSets=true",
        "BookStoreConnection": "Server=(localdb)\\mssqllocaldb;Database=C:\\USERS\\YVONN\\DOCUMENTS\\BOOKSTORE.MDF;Trusted_Connection=True;MultipleActiveResultSets=true"
    },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Warning"
    }
  }
}
接下來、加入 DB context 到 MVC 的 services 裡面。打開 template 幫我們建立的 Startup.cs,找到裡面的 ConfigureServices methods,加入以下code:

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    // Add Book's DB context
    services.AddDbContext(options =>
        options.UseSqlServer(Configuration.GetConnectionString("BookStoreConnection")));
            
     services.AddIdentity().AddEntityFrameworkStores().AddDefaultTokenProviders();
 
     services.AddMvc();

    // Add application services.
    services.AddTransient();
    services.AddTransient();
}

使用 Scaffolding Item 加入 BooksController.cs

最後一步,使用Scaffolding Item, 建立 BooksController.cs 我們就大功告成了。在 "Solution Explorer"中的 Controllers 點擊右鍵,Add -> New Scaffolded Item。選擇 "MVC Controller with views, using Entity Framework"
 在 "Add Controller" 中,把我們剛剛建立的 model class 與 data context 選取進來。
按下 "Add" 就大功告成了。

驗證

最後,把 Web Application 跑起來,進入http://localhost:50029/Books,加入一個 Harry Porter 來看看效果:

可以GitHub上找到 Demo Code:Source Code on GitHub