使用ASP.NET Core MVC 和 Entity Framework Core 開發一個CRUD(增刪改查)的應用程序
不定時更新翻譯系列,此系列更新毫無時間規律,文筆菜翻譯菜求各位看官老爺們輕噴,如覺得我翻譯有問題請挪步原博客地址
本文打算使用Entity Framework Core解釋ASP.NET Core MVC中的基本創建,讀取,更新和刪除(CRUD)操作。我們使用Entity Framework Code First
的方法開發應用程序 ,要設置ASP.NET Core MVC應用程序的開發環境,我們遵循本文中開始使用 ASP.NET Core MVC.的步驟。應用程序使用一個名為Book的實體來執行CRUD操作,並做一些簡單的演示。
更多精彩內容
創建數據庫
這個應用程序采用的是Entity Framework Core 中的Code First(代碼優先)方法,所以我們首先要添加Entity Framework Core ,這個應用程序使用的是SQL Server數據庫,因此我們需要提供SQL Server數據庫程序該,提供程序可通過名為 Microsoft.EntityFrameworkCore.SqlServer的 NuGet軟件包提供。當應用程序創建時,它包括Microsoft.AspNetCore.All NuGet元包。此包還包括Microsoft.EntityFrameworkCore.SqlServer,因此我們不必安裝它。
創建數據實體模型
應用程序在單個實體上執行CRUD操作,但是現在我們創建了兩個實體,這些實體分別是BaseEntity和Book。BaseEntity類具有公共屬性,,是其他實體的父類,並將由其他實體繼承。BaseEntity類按照下面的代碼片段創建。
using System;
namespace FirstCRUDApplication.DbEntities
{
public class BaseEntity
{
public Int64 Id { get; set; }
public DateTime AddedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string IPAddress { get; set; }
}
}
應用程序在名為Book的實體上執行CRUD操作。現在,我們創建一個Book類並繼承BaseEntity。
namespace FirstCRUDApplication.DbEntities
{
public class Book:BaseEntity
{
public string Name { get; set; }
public string ISBN { get; set; }
public string Author { get; set; }
public string Publisher { get; set; }
}
}
現在,讓我們為Book實體定義配置。數據庫表將使用Book實體的配置創建。定義配置有兩種選擇,一種是數據注釋 ,另一種是Fluent API。遵循SRP原則,我們使用第二個選項Fluent API定義實體配置。下面是BookMap類的代碼片段
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace FirstCRUDApplication.DbEntities
{
public class BookMap
{
public BookMap(EntityTypeBuilder<Book> entityBuilder)
{
entityBuilder.HasKey(t => t.Id);
entityBuilder.Property(t => t.Name).IsRequired();
entityBuilder.Property(t => t.ISBN).IsRequired();
entityBuilder.Property(t => t.Author).IsRequired();
entityBuilder.Property(t => t.Publisher).IsRequired();
}
}
}
EntityTypeBuilder<T>
支持Entity Framework Core的基礎結構。T表示被配置的實體。它使用方法定義每個字段的配置。讓我們看一下在前面的代碼中使用的一些方法。
- **HasKey: **
它設置了構成主鍵的實體屬性。 - Property: 它返回一個可以用來配置實體類型屬性的對象。
現在,我們創建了名為CRUDContext
的上下文類。它繼承自DbContext
。它是實體和數據庫之間的橋梁。它是一個主要類,它將數據作為對象進行交互。我們在上下文類中重寫OnModelCreating
方法。當我們使用Fluent API時,它定義了實體如何映射到數據庫。下面是名為CRUDContext.cs的上下文類的代碼片段。
using Microsoft.EntityFrameworkCore;
namespace FirstCRUDApplication.DbEntities
{
public class CRUDContext:DbContext
{
public CRUDContext(DbContextOptions<CRUDContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
new BookMap(modelBuilder.Entity<Book>());
}
}
}
使用EF連接數據庫
我們定義了一個帶有上下文的數據模型。現在,我們定義了數據庫和上下文之間的連接。我們必須遵循以下步驟,在應用程序中使用上下文。
- 我們定義一個連接字符串,以便將上下文連接到數據庫。打開appsetting.json文件,並根據以下代碼片段定義連接字符串。
"ConnectionStrings": {
"DefaultConnection": "Data Source=DESKTOP-RG33QHE;Initial Catalog=ApplicationDb;User ID=sa; Password=admin123"
}
它類似於web.config。它存儲配置級別設置,如連接字符串、SMTP、域名等。
- 應用程序配置從
Startup
類初始化。由於這個應用程序使用了Entity Framework Core,所以我們在使用中添加了兩個名稱空間。下面的代碼片段是相同的。
using FirstCRUDApplication.DbEntities;
using Microsoft.EntityFrameworkCore;
- ASP.NET Core提供了內置的控制反轉。在應用程序啟動時,上下文注冊到IoC。在此之后,使用構造函數依賴注入,上下文注入到MVC控制器中。因此,它在
Startup
類中注冊為一個服務。下面的代碼片段,用於配置上下文注冊為服務的ConfigureServices
方法。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<CRUDContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}
使用EF 遷移初始化數據庫
我們使用Entity Framework Core Migration來根據數據模型創建一個數據庫。為了執行遷移,我們可以使用軟件包管理器控制台(PMS)和命令行界面(CLI)。
Entity Framework Core工具CLI提供了 Microsoft.EntityFrameworkCore.Tool.DotNet 。要安裝這個包,我們不能使用install-package
命令或包管理器GUI。但是我們可以在應用程序中編輯.csproj文件,並將這個包添加到 DotNetCliToolReference,從而安裝這個包,下面的XML代碼是相同的。
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
</ItemGroup>
現在,我們需要遵循從數據模型創建新數據庫的步驟。這些都是
- 保存更改並構建項目。
- 打開解決方案文件夾位置。在解決方案瀏覽器中,右鍵單擊該項目並從上下文菜單中選擇打開文件資源管理器。
- 如下圖所示在地址欄中寫入cmd命令並按Enter鍵。
要發起遷移,請在命令窗口中輸入以下命令。
dotnet ef migrations添加了InitialCreate
圖1:Entity Framework Core Migration
現在,我們將遷移應用到數據庫。我們在命令窗口中輸入以下命令。該命令在其中創建數據庫和表。
dotnet ef database 修改
因此,我們在Entity Framework Core中使用code first
方法創建了數據庫
創建應用程序用戶界面
現在,我們為應用程序開發用戶界面。首先,我們為應用程序UI創建名為BookViewModel
的視圖模型。這個模型與視圖緊密地結合在一起。下面的代碼片段用於視圖模型。
using System.ComponentModel.DataAnnotations;
namespace FirstCRUDApplication.Models
{
public class BookViewModel
{
public long Id { get; set; }
public string Name { get; set; }
[Display(Name = "ISBN No")]
public string ISBN { get; set; }
public string Author { get; set; }
public string Publisher { get; set; }
}
}
現在,在控制器文件夾下創建一個名為 BookController
的控制器。該控制器具有執行CRUD操作的操作方法。CRUDContext類實例使用依賴注入注入它的構造函數。下面的代碼片段是一樣的。
using FirstCRUDApplication.DbEntities;
using FirstCRUDApplication.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace FirstCRUDApplication.Controllers
{
public class BookController : Controller
{
private CRUDContext context;
public BookController(CRUDContext context)
{
this.context = context;
}
[HttpGet]
public IActionResult Index()
{
IEnumerable<BookViewModel> model = context.Set<Book>().ToList().Select(b => new BookViewModel
{
Id= b.Id,
Name = b.Name,
ISBN = b.ISBN,
Author = b.Author,
Publisher = b.Publisher
});
return View("Index", model);
}
[HttpGet]
public IActionResult AddEditBook(long? id)
{
BookViewModel model = new BookViewModel();
if (id.HasValue)
{
Book book = context.Set<Book>().SingleOrDefault(c => c.Id == id.Value);
if (book != null)
{
model.Id = book.Id;
model.Name = book.Name;
model.ISBN = book.ISBN;
model.Author = book.Author;
model.Publisher = book.Publisher;
}
}
return PartialView("~/Views/Book/_AddEditBook.cshtml", model);
}
[HttpPost]
public IActionResult AddEditBook(long? id, BookViewModel model)
{
try
{
if (ModelState.IsValid)
{
bool isNew = !id.HasValue;
Book book = isNew ? new Book
{
AddedDate = DateTime.UtcNow
} : context.Set<Book>().SingleOrDefault(s => s.Id == id.Value);
book.Name = model.Name;
book.ISBN = model.ISBN;
book.Author = model.Author;
book.Publisher = model.Publisher;
book.IPAddress = Request.HttpContext.Connection.RemoteIpAddress.ToString();
book.ModifiedDate = DateTime.UtcNow;
if (isNew)
{
context.Add(book);
}
context.SaveChanges();
}
}
catch (Exception ex)
{
throw ex;
}
return RedirectToAction("Index");
}
[HttpGet]
public IActionResult DeleteBook(long id)
{
Book book = context.Set<Book>().SingleOrDefault(c => c.Id == id);
string bookName = book.Name;
return PartialView("~/Views/Book/_DeleteBook.cshtml", model: bookName);
}
[HttpPost]
public IActionResult DeleteBook(long id, IFormCollection form)
{
Book book = context.Set<Book>().SingleOrDefault(c => c.Id == id);
context.Entry(book).State = Microsoft.EntityFrameworkCore.EntityState.Deleted;
context.SaveChanges();
return RedirectToAction("Index");
}
}
}
現在,我們為每個CRUD操作開發用戶界面。視圖為添加和編輯圖書、圖書列表和刪除圖書而創建。我們來一個個的來看視圖。
圖書清單
這是應用程序的第一個視圖。它顯示了清單中的所有書籍。它以表格格式顯示圖書數據,並有一個添加新書的選項。圖書列表有編輯和刪除圖書的選項。它是一個名為index的索引視圖.cshtml在圖書文件夾的視圖。下面的代碼片段是一樣的。
@model IEnumerable<FirstCRUDApplication.Models.BookViewModel>
@using FirstCRUDApplication.Models
@using FirstCRUDApplication.Code
<div class="top-buffer"></div>
<div class="panel panel-primary">
<div class="panel-heading panel-head">Books</div>
<div class="panel-body">
<div class="btn-group">
<a id="createEditBookModal" data-toggle="modal" asp-action="AddEditBook" data-target="#modal-action-book" class="btn btn-primary">
<i class="glyphicon glyphicon-plus"></i> Add Book
</a>
</div>
<div class="top-buffer"></div>
<table class="table table-bordered table-striped table-condensed">
<thead>
<tr>
<th>Name</th>
<th>ISBN</th>
<th>Author</th>
<th>Publisher</th>
<th>Action</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.Name)</td>
<td>@Html.DisplayFor(modelItem => item.ISBN)</td>
<td>@Html.DisplayFor(modelItem => item.Author)</td>
<td>@Html.DisplayFor(modelItem => item.Publisher)</td>
<td>
<a id="editBookModal" data-toggle="modal" asp-action="AddEditBook" asp-route-id= "@item.Id" data-target="#modal-action-book"
class="btn btn-info">
<i class="glyphicon glyphicon-pencil"></i> Edit
</a>
<a id="deleteBookModal" data-toggle="modal" asp-action="DeleteBook" asp-route-id= "@item.Id" data-target="#modal-action-book" class="btn btn-danger">
<i class="glyphicon glyphicon-trash"></i> Delete
</a>
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
@Html.Partial("_Modal", new BootstrapModel { ID = "modal-action-book", AreaLabeledId = "modal-action-book-label", Size = ModalSize.Medium })
@section scripts
{
<script src="~/js/book-index.js" asp-append-version="true"></script>
}
現在,讓我們運行應用程序。作為第一個請求,它使用HttpGet請求調用index()的action方法,並將UI中列出的所有圖書作為響應,如圖2所示。
圖2:書清單界面
創建/編輯圖書視圖
由於創建和編輯視圖都是相同的,因此我們為這兩個視圖創建了一個公共視圖。這個視圖使用相同的BookViewModel
。讓我們定義一個創建/編輯的圖書部分視圖。下面是_AddEditBook.cshtml的代碼片段。
@model FirstCRUDApplication.Models.BookViewModel
@using FirstCRUDApplication.Models
<form asp-action="AddEditBook" role="form">
@await Html.PartialAsync("_ModalHeader", new ModalHeader { Heading = String.Format("{0} Book", @Model.Id == 0 ? "Add" : "Edit") })
<div class="modal-body form-horizontal">
<div class="form-group">
<label asp-for="Name" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="Name" class="form-control" />
</div>
</div>
<div class="form-group">
<label asp-for="ISBN" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="ISBN" class="form-control" />
</div>
</div>
<div class="form-group">
<label asp-for="Author" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="Author" class="form-control" />
</div>
</div>
<div class="form-group">
<label asp-for="Publisher" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="Publisher" class="form-control" />
</div>
</div>
</div>
@await Html.PartialAsync("_ModalFooter", new ModalFooter { })
</form>
應用程序在彈出窗口中執行數據操作。它使用Bootstrap模型彈出。一旦它在瀏覽器中打開,它就會在瀏覽器中保存。要從緩存和加載數據中刪除,我們按照以下代碼片段創建一個javascript文件。
(function ($) {
function Book() {
var $this = this;
function initilizeModel() {
$("#modal-action-book").on('loaded.bs.modal', function (e) {
}).on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
});
}
$this.init = function () {
initilizeModel();
}
}
$(function () {
var self = new Book();
self.init();
})
}(jQuery))
讓我們運行應用程序,點擊列表中的“添加書籍”按鈕或“編輯”按鈕。它稱之為AddEditBook
操作方法,它將部分視圖作為響應發送。圖3顯示了添加/編輯圖書的UI。
圖3:編輯圖書視圖UI
刪除視圖
讓我們執行最后的操作刪除。每個圖書數據在清單中都有一個delete按鈕。當用戶點擊“刪除”按鈕時,彈出顯示“你想刪除xxx嗎?”作為一個確認。這個刪除彈出框有兩個按鈕一個是刪除,另一個是取消。當用戶單擊彈出的刪除按鈕時,它會發出一個HttpPost請求,調用DeleteBook
操作方法並刪除書。下面是_DeleteBook.cshtml的代碼片段
@model String
@using FirstCRUDApplication.Models
@using (Html.BeginForm())
{
@Html.Partial("_ModalHeader", new ModalHeader { Heading = "Delete Book" })
<div class="modal-body form-horizontal">
Are you want to delete @Model?
</div>
@Html.Partial("_ModalFooter", new ModalFooter { SubmitButtonText="Delete"})
}
讓我們運行應用程序並單擊清單的Delete按鈕。它顯示模型中的UI,如圖4中刪除一本書。
圖4:確認刪除一本書
結論
本文使用ASP.NET Core和Entity Framework Core與code first開發應用程序並在模型彈出窗口中執行數據CRUD操作。這個演示的完整源代碼可以在GitHub上下載,點擊這里下載。
歡迎轉載,轉載請注明翻譯原文出處(本文章),原文出處(原博客地址),然后謝謝觀看
如果覺得我的翻譯對您有幫助,請點擊推薦支持:)