使用Angular 2, ASP。NET Core 1.1和实体框架核心(第1部分)

介绍 这是本系列的第一部分。在本系列中,我们将使用Angular 2、Asp创建一个SPA应用程序。Net Core 1.1和实体框架核心。这里我们使用Angular 2作为应用程序的UI,使用Asp。Net Core MVC我们将执行服务器端任务,而使用Entity Framework Core我们将执行所有的数据库级操作。在本系列中,我们将创建一个员工管理系统项目。在这个管理系统中,我们提供了查看所有员工列表、编辑现有员工、删除任何特定员工和输入新员工的功能。让我们浏览一下这个系列的议程。 议程 了解项目中添加实体框架的结构,创建新的页面来查看员工列表以及插入、更新和删除操作。执行Angular 2添加服务的路由 之前的请求 在开始进行本系列的工作之前,必须在系统中配置一些最低配置。 Visual Studio 2015 Update 3或Visual Studio 2017 . net Core 1.0类型脚本2.0 node .js Version 6或更高版本 在满足了以上所有要求之后,现在我们可以通过一些简单的步骤来设置SPA应用程序。 开始 最简单的开始方法是使用可用的项目模板之一。这些插件可插入标准的dotnet new命令,并可在Windows、Mac和Linux上运行。要安装(单页应用程序)SPA模板,打开命令提示符并运行以下命令。 安装微软。aspnetcore . spatemplate::* 上面的命令花了一些时间来安装几个SPA的模板,比如Angular, Knockout.js, React等等。所有这些模板的好处是,我们不需要担心整个安装过程。 要生成一个新项目,首先创建并清空文件夹,并将该项目命名为“EMS”,这里EMS是“员工管理系统”的缩写。创建空文件夹后,现在更改目录并转到这个项目。现在运行下面的命令“dotnet new angular”。 这个命令为Angular 2应用程序创建一个模板项目。现在运行“dotnet还原”命令nd,这个命令构建“MSBuild”文件并恢复所有的。net依赖。 在安装了所有的。net依赖项之后,现在我们要安装Node.js依赖项。运行“npm install”命令,该命令需要几分钟时间来安装所需的Node.js依赖项。 创建模板项目并安装所有必需的依赖项之后,现在运行“启动EMS”。csproj”命令。这个命令将在Visual Studio中打开你的项目,这里我使用的是Visual Studio 2017。 现在按“Ctrl + F5”运行项目。 运行项目后,如果你看到屏幕上方,那么恭喜你成功创建了Angular 2应用程序。如果你做任何的改变。ts" files or "。你将得到实时更新,只要你保存更改,不需要刷新浏览器。 应用程序的结构 成功创建并运行应用程序之后,让我们了解项目的结构。现在打开“解决方案资源管理器”窗口,你会发现下面的项目结构。 下面是我们的应用程序的主要部分。 依赖关系 这个部分包含了三种类型的依赖关系,“npm”依赖关系与我们的客户端应用程序相关,而“NuGet”包含。net核心级别的依赖关系。“SDK”部分包含系统级依赖关系。 launchSettings.json 这个json文件包含与每个调试配置文件相关联的项目特定设置,Visual Studio被配置为用于启动应用程序,包括应该使用的任何环境变量。此文件定义applicationURl、SSL端口号和身份验证模式。 wwwroot wwwroot部分包含了“dist”文件夹,这里dist文件夹包含了我们的“ClinetApp”编译后的代码。我们在模板(.ts)或.html页面中编写的所有代码都转换为编译后的代码并保存在“主客户机”中。js”文件。该文件包含我们在“ClientApp”文件夹中创建的所有组件、服务和所有其他资源的编译形式。 如果你去“索引”。您填充的“Home”控制器的视图发现我们引用了“主客户端”。js文件在应用程序启动过程中。 隐藏,复制Code

@{
    ViewData["Title"] = "Home Page";
}

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

<script src="~/dist/vendor.js" asp-append-version="true"></script>
@section scripts {
    <script src="~/dist/main-client.js" asp-append-version="true"></script>
}

ClientApp 这是我们项目的客户端部分,这里我们编写所有与Angular2相关的代码并创建组件和服务。App文件夹包含组件和“App .module”。ts”文件。“boot-client。文件定义了根组件选择器。 控制器 在本节中,我们将创建MVC控制器。在这个项目中,我们将使用controller从数据库中获取数据。 的观点 它定义了MVC项目的V部分,我想我们已经知道视图了。 Appsettings.json 而不是网络上。配置,你所有的设置现在都在appsettings中。它以键值对的形式包含所有配置信息。在这个文件中,我们定义了连接string和其他应用程序级别设置。 Packages.json 此文件包含所有与Angular2相关的依赖项。 Program.cs 这是应用程序的入口点,用于宿主应用程序。在这个文件中,我们简单地做配置的工作。使用WebHostBuilder启动主机 Startup.cs cs文件像一个中间件一样工作,提供系统运行所需的所有服务。 tsconfig.cs 此文件包含类型脚本配置设置。 Webpack.config.js Webpack的工作方式类似于包管理器和模块绑定器。它获取所有具有依赖关系的项目模块,并生成表示这些模块的静态资产。Webpack和构建和捆绑CSS, JavaScript文件,图像所有其他静态内容。 配置实体框架 现在我们使用代码优先的方法创建数据库和表。在我们的应用程序中,我们将使用SQL Server作为数据库,因此我们需要为SQL Server安装实体框架。要为SQL Server配置实体框架,我们需要添加SQL Server数据库提供程序。 打开“包管理器控制台”并运行以下命令。 “安装包Microsoft.EntityFrameworkCore.SqlServer” 我们将使用一些实体框架工具来维护数据库。因此,我们还需要安装这些工具包。因此,运行下面的命令来添加所有必需的工具。 “安装包Microsoft.EntityFrameworkCore.Tools” 创建实体类 在为实体框架添加依赖项之后,让我们创建Employee和Project实体类。b/w员工和项目实体之间存在多对一的关系,这意味着一个员工一次只能有一个项目,但在一个项目中可以有多个员工。首先创建一个“Model”文件夹,并在这个文件夹中添加“Employee”类。 Employee实体 在Models文件夹中添加一个Employee类,并用以下代码替换Employee类的代码。 隐藏,复制Code

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EMS.Models
{
    public class Employee
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int EmployeeId { get; set; }
        public string EmployeeName { get; set; }
        public string Designation { get; set; }
        public string Skills { get; set; }
        public int ProjectId { get; set; }
        public Project Project { get; set; }
    }
}

在上面的代码中,EmployeeId属性是Employee实体的主键,也是标识类型。ProjectId为外键,对应的导航属性为Project。 项目法人 现在,在Model文件夹中添加另一个类,并将这个类命名为“Project”,用下面的代码替换这个类的代码。 隐藏,复制Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace EMS.Model
{
    public class Project
    {
        public int ProjectId { get; set; }
        public string ProjectName { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
    }
}

ProjectId属性是此实体的主键,其他属性定义关于项目的信息。 添加DbContext类 任何实体框架结构的主要类都是DbCntext类。在这个类中,我们定义了用于在数据库中创建表的所有实体。现在在模型文件夹中添加另一个类并命名为“EmployeeContext”。这个类将派生自“System.Data.Entity”。DbContext”类。将该类中的代码替换为以下代码。 隐藏,复制Code

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

namespace EMS.Model
{
    public class EmployeeContext:DbContext   
     {  
        public EmployeeContext(DbContextOptions<EmployeeContext> options):base(options)  
        {  
  
        }
        public DbSet<Employee> Employee { get; set; }
        public DbSet<Project> Project { get; set; }  
    }  
}

在上面的代码中,我们为Employee和Project class定义了两个Dbset属性,这个属性将在database中创建两个表,并且名称将与在Dbset中定义的属性相同。 使用依赖项注入注册上下文 在创建了所有实体和dbContext类之后,现在我们为实体框架添加一个服务,这样任何需要此服务的组件都可以由构造函数提供。在控制器构造函数中,我们使用此服务来获取上下文实例。现在开放”启动。并将以下代码添加到“配置服务”方法中。 隐藏,复制Code

services.AddDbContext<EmployeeContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

在上面的代码中,我们为DbContext注册了一个服务,这里的“DefaultConnection”提供了在我们的“appsets .json”中定义的连接字符串。现在打开你的“appsettings”。文件,并添加以下代码。将服务器名称替换为SQL服务器名称。 隐藏,复制Code

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=*******;Database=Employee;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

添加迁移和创建数据库 在配置了dbContext和实体类之后,现在我们添加迁移,并使用“Update-Database”命令创建我们的项目数据库。因此,首先我们为此添加迁移,打开您的“包管理器控制台”,运行“add - migration firstMigration”命令。此命令将在项目中添加Migrations文件夹,Migrations文件夹中的第一个文件包含如何创建数据库的所有信息。 现在我们将运行“Update-Database”命令,该命令获取迁移类中可用的代码并更新数据库。在我们的例子中,这个命令在SQL Server中创建一个“Employee”数据库,其中包含我们在前面的模型类中定义的所有表和属性。 现在打开你的SQL服务器,你会发现“雇员”数据库已经被添加。 添加初始数据 现在我们的表和数据库已经准备好了,让我们向表中添加一些首字母数据。 将数据添加到项目表中 隐藏,复制Code

INSERT INTO dbo.Project  
(  
    ProjectName,  
    StartDate,  
     EndDate  
)  
VALUES( N'Lions',CAST('02/01/2017' as datetime),CAST('04/05/2017' AS datetime) ),(  N'OUP',CAST('08/09/2016' AS datetime),CAST('12/03/2017' AS datetime) ),  
(   N'VMesh',CAST('12/04/2016' as date),CAST('04/01/2017' as date) )

将数据添加到Employee表中 隐藏,复制Code

insert into Employee  
(Designation,EmployeeName,ProjectId,Skills)  
values('Developer','Raj Kumar',2,'C#,Asp.Net,MVC'),  
('Mobile Developer','Ankur Verma',3,'Java, Android Studio, Xamarin'),  
('Developer','Dheeraj Sharma',1,'C#,Asp.Net,MVC,AngularJS'),  
('Developer','Dhramveer',2,'C#,Asp.Net,MVC,AngularJS,Node.js'),  
('Mobile Developer','Shivam Kumar',1,'Java, Android Studio, Xamarin')

现在我们的数据库和应用程序设置已经就绪,让我们开始处理应用程序的视图部分。 显示员工列表 现在转到app.modules。ts文件在App文件夹。在这个文件中,你会发现一些默认路由被定义为“counter”、“home”和“获取数据”。我们不需要所有这些路由,所以从路由表删除“counter”和“fetchdata”路由,也从components部分删除这些组件。在所有这些变化之后,现在去"navmenu.component.html"文件,并删除"Counter"和"Fetch Data"项目从"navmenu.component.html"。 经过上述所有更改,现在我们的应用程序看起来如下所示。 现在我们添加一些项目中需要的组件。 雇员详细信息组件 现在我们添加一个详细信息组件,使用这个组件我们将显示一个雇员的详细信息。 右键点击“components”文件夹,并添加一个新的文件夹,并将该文件夹命名为“details”。此文件夹包含员工详细信息组件的内容。现在在这个文件夹中添加一个typescript文件,并将其命名为“details.component.ts”,然后粘贴在下面。 隐藏,复制Code

import { Component } from '@angular/core';

@Component({
    selector: 'employee-detail',
    templateUrl: './details.component.html'
})
export class DetailsComponent {
    
}

现在我们需要为该组件创建一个模板文件,因此右键单击“details”文件夹和一个html文件,并将该文件命名为“details.component.html”,然后粘贴以下代码。 隐藏,复制Code

<h2>This is Detail Component</h2>

编辑员工组件 在这个项目中,我们将提供编辑任何现有员工的详细信息的功能,为此,我们需要添加一个“editEmployee”组件。右键单击components文件夹并添加一个新文件夹并将该文件夹命名为"editEmployee"现在添加一个typescript文件并将该文件命名为“editEmployee.component.ts”并粘贴下面的代码。 隐藏,复制Code

import { Component } from '@angular/core';

@Component({
    selector: 'edit-employee',
    templateUrl: './editEmployee.component.html'
})
export class editEmployeeComponent {

}

现在添加html模板文件,将该文件命名为“editEmployee.component.html”并粘贴以下代码。 隐藏,复制Code

<h1>Edit Employee</h1>

新员工组件 在这个组件中,我们编写代码为员工输入一个新条目。右键点击“components”文件夹并添加“newEmployee”文件夹。添加一个typescript文件并将该文件命名为“newEmployee.component.ts”并粘贴下面的代码。 隐藏,复制Code

import { Component } from '@angular/core';

@Component({
    selector: 'new-employee',
    templateUrl: './newEmployee.component.html'
})
export class newEmployeeComponent {

}

现在添加一个html模板文件,并将该文件命名为“newEmployee.component.html”,然后粘贴下面的代码。 隐藏,复制Code

<h1>This is New Employee  component</h1>

在添加了项目所需的所有组件后,现在“ClinetApp”部分的结构如下所示。 为组件添加路由 在添加了所有必需的组件之后,现在我们将为这些组件执行路由。“app.modules开放。文件,并将以下代码粘贴到此文件中。 隐藏,收缩,复制Code

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { UniversalModule } from 'angular2-universal';
import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { DetailsComponent } from './components/details/details.component';
import { newEmployeeComponent } from './components/newEmployee/newEmployee.component';
import { editEmployeeComponent } from './components/editEmployee/editEmployee.component';


@NgModule({
    bootstrap: [ AppComponent ],
    declarations: [
        AppComponent,
        NavMenuComponent,
        HomeComponent,
        DetailsComponent,
        newEmployeeComponent,
        editEmployeeComponent
    ],
    imports: [
        UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
        RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: HomeComponent },
            { path: 'details/:id', component: DetailsComponent },
            { path: 'new', component: newEmployeeComponent },
            { path: 'edit/:id', component: editEmployeeComponent },
            { path: '**', redirectTo: 'home' }
        ])
    ]
})
export class AppModule {
}

在上面的代码中,我们注册了“声明”部分中的所有组件,并为所有这些组件执行路由。 在导航菜单中添加新项目 打开"navmenu.component.html"文件并将以下代码粘贴到该文件中。 隐藏,收缩,复制Code

<divclass='main-nav'>
    <divclass='navbar navbar-inverse'>
        <divclass='navbar-header'>
            <buttontype='button'class='navbar-toggle'data-toggle='collapse'data-target='.navbar-collapse'>
                <spanclass='sr-only'>Toggle navigation</span>
                <spanclass='icon-bar'></span>
                <spanclass='icon-bar'></span>
                <spanclass='icon-bar'></span>
            </button>
            <aclass='navbar-brand'[routerLink]="['/home']">EMS</a>
        </div>
        <divclass='clearfix'></div>
        <divclass='navbar-collapse collapse'>
            <ulclass='nav navbar-nav'>
                <li[routerLinkActive]="['link-active']">
                    <a[routerLink]="['/home']">
                        <spanclass='glyphicon glyphicon-home'></span> Home
                    </a>
                </li>
                <li[routerLinkActive]="['link-active']">
                    <a[routerLink]="['/new']">
                        <spanclass='glyphicon glyphicon-user'></span> New Employee
                    </a>
                </li>
            </ul>
        </div>
    </div>
</div>

在上面的代码中,我们添加了“新员工”项目nav菜单。点击这个菜单项,我们可以打开“新员工”页面,并为员工添加一个新条目。 到目前为止,我们已经创建了所有的组件,也执行路由和添加一个新的项目在nav菜单。让我们检查一下这些改变是否有效。运行此应用程序时,将打开以下屏幕。 当你点击“新员工”菜单项时,下面的屏幕会显示出来。 显示员工列表 在我们的项目主页中,我们将显示所有员工的列表。我们显示员工的“EmployeeName”、“指定”、“Project”信息。首先,我们需要创建一个API,使用它我们可以获得所有员工的列表。现在转到“Controllers”文件夹和一个新的“API Controller”,将其命名为“EmployeeController”并粘贴以下代码。 隐藏,收缩,复制Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using EMS.Model;
using EMS.ViewModel;
using Microsoft.EntityFrameworkCore;

namespace EMS.Controllers
{
    [Produces("application/json")]
    [Route("api/Employee")]
    public class EmployeeController : Controller
    {
        private readonly EmployeeContext _context;

        public EmployeeController(EmployeeContext context)
        {
            _context = context;
        }
        [HttpGet]
        public async Task<IActionResult> EmployeeList()
        {
            List<Employee_Project> ilIst = new List<Employee_Project>();
            var listData = await (from emp in _context.Employee
                                  join pro in _context.Project on emp.ProjectId equals pro.ProjectId
                                  select new
                                  {
                                      emp.EmployeeId,
                                      emp.EmployeeName,
                                      emp.Designation,
                                      pro.ProjectName

                                  }
                          ).ToListAsync();
            listData.ForEach(x =>
            {
                Employee_Project Obj = new Employee_Project();
                Obj.EmployeeId = x.EmployeeId;
                Obj.Designation = x.Designation;
                Obj.EmployeeName = x.EmployeeName;
                Obj.Project = x.ProjectName;
                ilIst.Add(Obj);
            });

            return Json(ilIst);
        }
    }
}

在上面的代码行中,我们创建了一个异步方法。异步编程是Asp的默认模式。净的核心。异步编程提供了一种以非阻塞模式编写代码的机制。我们创建了一个异步的雇员列表方法。在代码的第一行“List<Employee_Project>我们创建了一个“Employee_Project”视图模型类型的列表。这里的“Employee_Project”是一个视图模型。 ViewModel Asp。Net MVC只用于显示所需的信息,ViewModel也用于显示来自两个或更多模型的数据。现在我们在项目中添加一个ViewModel文件夹。在项目中添加一个新的文件夹并命名为“ViewModels”。创建“viewModels”文件夹后,在viewModels文件夹中添加一个类。右键单击“ViewModels”文件夹并添加一个新类,将这个类命名为“Employee_Project”。创建类之后,现在在该类中粘贴以下代码。 隐藏,复制Code

namespace EMS.ViewModel
{
    public class Employee_Project
    {
        public int EmployeeId { get; set; }
        public string EmployeeName { get; set; }
        public string Designation { get; set; }
        public string Project { get; set; }
    }
}

使用linq查询,我们获得关于所有员工的“EmployeeId”、“EmployeeName”、“指定”、“ProjectName”信息,并使用“ForEach”方法将这些值添加到“iList”对象中。在代码的最后一行中,我们将ilist数据转换为JSON格式,并将JSON结果返回给所需的资源。 现在我们的API已经准备好返回雇员列表让我们检查它是否工作。打开浏览器并粘贴“http://localhost:54273/api/employee”URL并按回车。如果你得到JSON结果,这意味着我们的API工作完美。 没有当我们的API准备返回员工列表时,让我们使用这个API并显示员工信息。我们需要一个能够使用这个API并获得结果的服务。在“app”部分添加“Service”文件夹。在创建文件夹之后,添加一个typescript文件并将该文件命名为“services”。然后将下面的代码粘贴到这个文件中。 隐藏,复制Code

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class EmployeeServcies {
    constructor(private http: Http) {
       
    }
    getEmployeeList() {
        return this.http.get('http://localhost:54273/api/employee');
    }
}

在上面的代码中,我们创建了一个“EmployeeServcies”类,并用“@Injectable”元数据修饰它。元数据被用来将一个类定义为服务。在这个服务类中,我们添加了“getEmployeeList”方法,在这个方法中,我们使用“HTTP”类的“get”方法来执行对服务器的HTTP get请求。 创建服务之后,现在我们需要在“app.modules”中注册该服务。ts”文件。打开你的“app.modules。“将此服务归档并导入,并将此服务注册到提供商”。我们在app.modules中注册了这个服务。这意味着现在这个服务是全局服务,我们可以在任何组件中使用这个服务,我们不需要在每个组件中注册这个服务。 在创建并注册了服务之后,现在我们在home组件中使用该服务,因此打开“home.component.ts”文件并粘贴下面的代码。 隐藏,复制Code

import { Component } from '@angular/core';
import { EmployeeServcies } from '../../Services/services';
import { Response } from '@angular/http';
@Component({
    selector: 'home',
    templateUrl: './home.component.html'
})
export class HomeComponent {
    public EmployeeList = [];
    public constructor(private empService: EmployeeServcies) {
        this.empService.getEmployeeList()
            .subscribe(
            (data: Response) => (this.EmployeeList= data.json())
            );

    }
}

在上面的代码中,我们创建了一个“EmployeeServcies”服务的实例(empService),并使用该服务的“getEmployeeList”方法来获取员工列表。您可以看到,我们正在使用“订阅”。实际上,angular 2为运行异步请求提供了一种新的模式,叫做Observables, http是angular 1的$http的继承者。它的http.get()方法不是返回一个承诺,而是返回一个可观察对象。使用"subscribe"方法,我们可以使用可观察对象,"subscribe"方法告诉可观察对象"你在这里执行你的任务,有人列出并监视你,并在你返回结果时执行那个回调函数"在订阅方法中,我们获取数据并将数据分配到“EmployeeList”中,现在我们使用这个列表来显示员工列表。 打开"home.component.html"文件并粘贴以下代码。 隐藏,收缩,复制Code

<div class="row">
    <div class="col-md-12">
        <h3>Employee List</h3>
        <br />
        <br />
        <br />
    </div>
    
</div>
<div class="row">
    <div class="table-responsive">
        <table class="table">
            <thead>
                <tr>
                    <th>
                        S.No.
                    </th>
                    <th>
                        EmployeeName
                    </th>
                    <th>
                        Designation
                    </th>
                    <th>
                        Project
                    </th>
                    <th>
                        Action
                    </th>
                </tr>
            </thead>
            <tbody>
                
                <tr *ngFor="let empData of EmployeeList; let i = index; trackBy: employeeId">
                    <td>
                        {{i+1}}
                    </td>
                    <td>
                        {{empData.employeeName}}
                    </td>
                    <td>
                       {{empData.designation}}
                    </td>
                    <td>
                       {{empData.project}}
                    </td>
                    <td>

                        <a [routerLink]="['/details/',empData.employeeId]"
                           class="btn btn-primary">
                            Detail
                        </a>
                        <a [routerLink]="['/edit/',empData.employeeId]"
                           class="btn btn-success">
                            Edit
                        </a>
                        <a 
                           class="btn btn-danger">
                            Delete
                        </a>
                    </td>
                </tr>
                
        </table>
    </div>
</div>

在上面的代码中,我们对“EmployeeList”执行“*ngFor”并创建一个员工列表。我们还为每个员工条目添加了三个锚标记(Edit、Delete和Detail)。我们使用“routerLink”将锚标签链接到应用程序的特定部分。 完成所有更改之后,现在保存项目并刷新浏览器,您将得到以下结果。 总结 这是“使用Angular 2, Asp的SPA”的第一部分。Net Core 1.1和实体框架核心系列。今天我们学习如何使用Angular2来setup.net core项目,并了解项目的结构。我们还在这个项目中执行了EF Core(实体框架)的设置。我们创建一些组件,并为这些组件执行路由。创建服务,使用内置的“http”服务从Web API获取数据,并将这些数据显示为表格格式。在下一篇文章中,我们将创建一些屏幕来添加、删除或编辑员工信息。我们还提供了搜索和排序员工信息的功能。 本文转载于:http://www.diyabc.com/frontweb/news17309.html

原文地址:https://www.cnblogs.com/Dincat/p/13494009.html