使用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上下载,点击这里下载。
    
     欢迎转载,转载请注明翻译原文出处(本文章),原文出处(原博客地址),然后谢谢观看
    
   
    
     如果觉得我的翻译对您有帮助,请点击推荐支持:)
    
   
 
