使用ASP.NET Core MVC 和 Entity Framework Core 开发一个CRUD(增删改查)的应用程序
不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址
本博文翻译自:
http://l-knowtech.com/2017/08/28/first-crud-application-asp-net-core-mvc-using-entity-framework-core/
本文打算使用ASP.NET Core MVC和Entity Framework Core在ASP中解释基本的创建、读取、更新和删除(CRUD)操作。我们使用Entity Framework Code First(代码优先)的方法为 ASP.NET Core MVC应用程序创建开发环境,我们遵循本文中开始使用 ASP.NET Core MVC.的步骤。应用程序使用一个名为Book的实体来执行CRUD操作,并做一些简单的演示。
更多精彩内容
- 开始使用 ASP.NET Core MVC
创建数据库
这个应用程序采用的是Entity Framework Core 中的Code First(代码优先)方法,所以我们首先要添加Entity Framework Core ,这个应用程序使用的是SQL Server数据库,因此我们需要提供SQL Server数据库程序
创建数据实体模型
应用程序在单个实体上执行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实体的配置创建。定义配置有两种选择,一种是Data Annotation ,另一种是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、Domain。
-
应用程序配置从
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 Migration初始化数据库
我们使用Entity Framework Core Migration来根据数据模型创建一个数据库。为了执行迁移,我们可以使用Package Manager Console(PMS)和Command Line Interface(CLI)。
Entity Framework Core工具CLI提供了
Microsoft.EntityFrameworkCore.Tool.DotNet
。要安装这个包,我们不能使用安装包命令或包管理器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上下载,点击这里下载。
欢迎转载,转载请注明翻译原文出处(本文章),原文出处(原博客地址),然后谢谢观看
如果觉得我的翻译对您有帮助,请点击推荐支持:)