使用 ASP.NET Core, Entity Framework Core 和 ABP 创建N层Web应用 第二篇

介绍

这是“使用 ASP.NET Core ,Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用”系列文章的第二篇。以下可以看其他篇目:

  • 使用 ASP.NET Core ,Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用  第一篇 (翻译版本链接)

应用开发

创建 Person 实体

我们将任务分配给具体的人,所以添加一个责任人的概念。我们定义一个简单的 Person 实体。

代码如下

[Table("AppPersons")]

public class Person : AuditedEntity<Guid>

{

    public const int MaxNameLength = 32;


    [Required]

    [MaxLength(MaxNameLength)]

    public string Name { get; set; }


    public Person()

    {

            

    }


    public Person(string name)

    {

        Name = name;

    }

}

这一次,我们作为示范,将 Id (主键)设置为 Guid 类型。同时,这次不从 base Entity 继承,而是从 AuditedEntity 继承 (该类定义了多个常用属性 创建时间 CreationTime, 创建者用户Id CreaterUserId, 最后修改时间 LastModificationTime 和最后修改人Id LastModifierUserId )

 

关联 Person 到 Task 实体

我们同时将 责任人 AssignedPerson 属性添加到 任务 Task 实体中(如下代码只粘贴修改的部分)

代码如下

[Table("AppTasks")]

public class Task : Entity, IHasCreationTime

{

    //...


    [ForeignKey(nameof(AssignedPersonId))]

    public Person AssignedPerson { get; set; }

    public Guid? AssignedPersonId { get; set; }


    public Task(string title, string description = null, Guid? assignedPersonId = null)

        : this()

    {

        Title = title;

        Description = description;

        AssignedPersonId = assignedPersonId;

    }

}

责任人 AssignedPerson 是可选的。所以,任务可以指派给责任人或者不指派

 

添加 Person 到 数据库上下文 DbContext

最后,我们添加新的责任人 Person 实体到 DbContext 类中:

代码如下

public class SimpleTaskAppDbContext : AbpDbContext

{

    public DbSet<Person> People { get; set; }

    

    //...

}

添加 Person 实体的新迁移文件

现在,我们在 源包管理控制台 Package Manager Console 中执行迁移命令,如图所示

该命令将会在项目里创建新的数据迁移类。

代码如下

public partial class Added_Person : Migration

{

    protected override void Up(MigrationBuilder migrationBuilder)

    {

        migrationBuilder.CreateTable(

            name: "AppPersons",

            columns: table => new

            {

                Id = table.Column<Guid>(nullable: false),

                CreationTime = table.Column<DateTime>(nullable: false),

                CreatorUserId = table.Column<long>(nullable: true),

                LastModificationTime = table.Column<DateTime>(nullable: true),

                LastModifierUserId = table.Column<long>(nullable: true),

                Name = table.Column<string>(maxLength: 32, nullable: false)

            },

            constraints: table =>

            {

                table.PrimaryKey("PK_AppPersons", x => x.Id);

            });


        migrationBuilder.AddColumn<Guid>(

            name: "AssignedPersonId",

            table: "AppTasks",

            nullable: true);


        migrationBuilder.CreateIndex(

            name: "IX_AppTasks_AssignedPersonId",

            table: "AppTasks",

            column: "AssignedPersonId");


        migrationBuilder.AddForeignKey(

            name: "FK_AppTasks_AppPersons_AssignedPersonId",

            table: "AppTasks",

            column: "AssignedPersonId",

            principalTable: "AppPersons",

            principalColumn: "Id",

            onDelete: ReferentialAction.SetNull);

    }


    //...

}

该类为自动生成的,我们只是将 ReferentialAction.Restrict 修改为 ReferentialAction.SetNull 。它的作用是:当我们删除一个责任人的时候,分配给这个人的任务会变成为分配。在这个 demo 里,这并不重要。我们只是想告诉你,如果有必要的话,迁移类的代码是可以修改的。实际上,我们总是应该在执行到数据库之前,重新阅读生成的代码。

之后,我们可以对我们的数据库执行迁移了。如下图:(更多迁移相关信息请参照  entity framework documentation )

当我们打开数据库的时候,我们可以看到表和字段都已经创建完毕了,我们可以添加一些测试数据。如下图:

我们添加一个责任人并分配第一个任务给他。如下图:

 

返回任务列表中的责任人 Person

我们将修改 TaskAppService ,使之可以返回责任人信息。首先,我们在 TaskListDto 中添加2个属性。

代码如下 (只显示有变动的代码,如需看完整代码请参考第一篇,下同)

[AutoMapFrom(typeof(Task))]

public class TaskListDto : EntityDto, IHasCreationTime

{

    //...


    public Guid? AssignedPersonId { get; set; }


    public string AssignedPersonName { get; set; }

}

同时将 Task.AssignedPerson 属性添加到查询里,仅添加 Include 行即可

代码如下

public class TaskAppService : SimpleTaskAppAppServiceBase, ITaskAppService

{

    //...


    public async Task<ListResultDto<TaskListDto>> GetAll(GetAllTasksInput input)

    {

        var tasks = await _taskRepository

            .GetAll()

            .Include(t => t.AssignedPerson)

            .WhereIf(input.State.HasValue, t => t.State == input.State.Value)

            .OrderByDescending(t => t.CreationTime)

            .ToListAsync();


        return new ListResultDto<TaskListDto>(

            ObjectMapper.Map<List<TaskListDto>>(tasks)

        );

    }

}

这样, GetAll 方法会返回任务及相关的责任人信息。由于我们使用了 AutoMapper , 新的属性也会自动添加到 DTO 里。

 

单元测试责任人 Person


在这里,我们修改单元测试,(对测试不感兴趣者可直接跳过)看看获取任务列表时是否能获取到责任人。首先,我们修改 TestDataBuilder 类里的初始化测试数据,分配任务给责任人。

代码如下

public class TestDataBuilder

{

    //...


    public void Build()

    {

        var neo = new Person("Neo");

        _context.People.Add(neo);

        _context.SaveChanges();


        _context.Tasks.AddRange(

            new Task("Follow the white rabbit", "Follow the white rabbit in order to know the reality.", neo.Id),

            new Task("Clean your room") { State = TaskState.Completed }

            );

    }

}

然后我们修改 TaskAppService_Tests.Should_Get_All_Tasks() 方法,检查是否有一个任务已经指派了责任人(请看代码最后一行)

代码如下

[Fact]

public async System.Threading.Tasks.Task Should_Get_All_Tasks()

{

    //Act

    var output = await _taskAppService.GetAll(new GetAllTasksInput());


    //Assert

    output.Items.Count.ShouldBe(2);

    output.Items.Count(t => t.AssignedPersonName != null).ShouldBe(1);

}

友情提示:扩张方法 Count 需要使用 using System.Linq 语句。

 

在任务列表页展示责任人的名字

最后,我们修改 Task\Index.cshtml 来展示 责任人的名字 AssignedPersonName 。

代码如下

@foreach (var task in Model.Tasks)

{

    <li class="list-group-item">

        <span class="pull-right label label-lg @Model.GetTaskLabel(task)">@L($"TaskState_{task.State}")</span>

        <h4 class="list-group-item-heading">@task.Title</h4>

        <div class="list-group-item-text">

            @task.CreationTime.ToString("yyyy-MM-dd HH:mm:ss") | @(task.AssignedPersonName ?? L("Unassigned"))

        </div>

    </li>

}

启动程序,我们可以看到任务列表入下图:

 

任务创建的新应用服务方法

现在我们可以展示所有的任务,但是我们却还没有一个任务创建页面。首先,在 ITaskAppService 接口里添加一个 Create 方法。

代码如下

public interface ITaskAppService : IApplicationService

{

    //...


    System.Threading.Tasks.Task Create(CreateTaskInput input);

}

然后在 TaskAppService 类里实现它

代码如下

public class TaskAppService : SimpleTaskAppAppServiceBase, ITaskAppService

{

    private readonly IRepository<Task> _taskRepository;


    public TaskAppService(IRepository<Task> taskRepository)

    {

        _taskRepository = taskRepository;

    }


    //...


    public async System.Threading.Tasks.Task Create(CreateTaskInput input)

    {

        var task = ObjectMapper.Map<Task>(input);

        await _taskRepository.InsertAsync(task);

    }

}

Create 方法会自动映射输入参数 input 到task 实体,之后我们使用仓储 repository 来将任务实体插入数据库中。让我们来看看输入参数 input 的 CreateTaskInput DTO 。

代码如下

using System;

using System.ComponentModel.DataAnnotations;

using Abp.AutoMapper;


namespace Acme.SimpleTaskApp.Tasks.Dtos

{

    [AutoMapTo(typeof(Task))]

    public class CreateTaskInput

    {

        [Required]

        [MaxLength(Task.MaxTitleLength)]

        public string Title { get; set; }


        [MaxLength(Task.MaxDescriptionLength)]

        public string Description { get; set; }


        public Guid? AssignedPersonId { get; set; }

    }

}

我们将DTO配置为映射到任务 Task 实体(使用 AutoMap 特性),同时添加数据验证 validation 。我们使用任务 Task 实体的常量来同步设置最大字串长度。 

 

测试任务创建服务

我们添加 TaskAppService_Tests 类的集成测试来测试 Create 方法:(如果对测试不感兴趣者可以跳过这个部分

代码如下

using Acme.SimpleTaskApp.Tasks;

using Acme.SimpleTaskApp.Tasks.Dtos;

using Shouldly;

using Xunit;

using System.Linq;

using Abp.Runtime.Validation;


namespace Acme.SimpleTaskApp.Tests.Tasks

{

    public class TaskAppService_Tests : SimpleTaskAppTestBase

    {

        private readonly ITaskAppService _taskAppService;


        public TaskAppService_Tests()

        {

            _taskAppService = Resolve<ITaskAppService>();

        }


        //...


        [Fact]

        public async System.Threading.Tasks.Task Should_Create_New_Task_With_Title()

        {

            await _taskAppService.Create(new CreateTaskInput

            {

                Title = "Newly created task #1"

            });


            UsingDbContext(context =>

            {

                var task1 = context.Tasks.FirstOrDefault(t => t.Title == "Newly created task #1");

                task1.ShouldNotBeNull();

            });

        }


        [Fact]

        public async System.Threading.Tasks.Task Should_Create_New_Task_With_Title_And_Assigned_Person()

        {

            var neo = UsingDbContext(context => context.People.Single(p => p.Name == "Neo"));


            await _taskAppService.Create(new CreateTaskInput

            {

                Title = "Newly created task #1",

                AssignedPersonId = neo.Id

            });


            UsingDbContext(context =>

            {

                var task1 = context.Tasks.FirstOrDefault(t => t.Title == "Newly created task #1");

                task1.ShouldNotBeNull();

                task1.AssignedPersonId.ShouldBe(neo.Id);

            });

        }


        [Fact]

        public async System.Threading.Tasks.Task Should_Not_Create_New_Task_Without_Title()

        {

            await Assert.ThrowsAsync<AbpValidationException>(async () =>

            {

                await _taskAppService.Create(new CreateTaskInput

                {

                    Title = null

                });

            });

        }

    }

}

第一个测试创建了一个带 title 的任务, 第二个测试创建了一个带 title 和 责任人 的测试,最后一个测试创建了一个无效的任务来展示 exception 例子。

 

任务创建页面


我们现在知道 TaskAppService.Create 方法可以正常工作了。现在,我们可以创建一个页面来添加新任务了。完成后的效果如下图所示:

首先,我们在任务控制器 TaskController 添加一个 Create action 。

代码如下

using System.Threading.Tasks;

using Abp.Application.Services.Dto;

using Acme.SimpleTaskApp.Tasks;

using Acme.SimpleTaskApp.Tasks.Dtos;

using Acme.SimpleTaskApp.Web.Models.Tasks;

using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Mvc.Rendering;

using System.Linq;

using Acme.SimpleTaskApp.Common;

using Acme.SimpleTaskApp.Web.Models.People;


namespace Acme.SimpleTaskApp.Web.Controllers

{

    public class TasksController : SimpleTaskAppControllerBase

    {

        private readonly ITaskAppService _taskAppService;

        private readonly ILookupAppService _lookupAppService;


        public TasksController(

            ITaskAppService taskAppService,

            ILookupAppService lookupAppService)

        {

            _taskAppService = taskAppService;

            _lookupAppService = lookupAppService;

        }


        //...

        

        public async Task<ActionResult> Create()

        {

            var peopleSelectListItems = (await _lookupAppService.GetPeopleComboboxItems()).Items

                .Select(p => p.ToSelectListItem())

                .ToList();


            peopleSelectListItems.Insert(0, new SelectListItem { Value = string.Empty, Text = L("Unassigned"), Selected = true });


            return View(new CreateTaskViewModel(peopleSelectListItems));

        }

    }

}

我们将 ILookupAppService 反射进来,这样可以获取责任人下拉框的项目。本来我们是可以直接反射使用 IRepository<Person,Guid> 的,但是为了更好的分层和复用,我们还是使用 ILookUpAppService 。ILookupAppService.GetPeopleComboboxItems 在应用层的定义如下:

代码如下

public interface ILookupAppService : IApplicationService

{

    Task&lt;ListResultDto&lt;ComboboxItemDto>> GetPeopleComboboxItems();

}


public class LookupAppService : SimpleTaskAppAppServiceBase, ILookupAppService

{

    private readonly IRepository&lt;Person, Guid> _personRepository;


    public LookupAppService(IRepository&lt;Person, Guid> personRepository)

    {

        _personRepository = personRepository;

    }


    public async Task&lt;ListResultDto&lt;ComboboxItemDto>> GetPeopleComboboxItems()

    {

        var people = await _personRepository.GetAllListAsync();

        return new ListResultDto&lt;ComboboxItemDto>(

            people.Select(p => new ComboboxItemDto(p.Id.ToString("D"), p.Name)).ToList()

        );

    }

}

ComboboxItemDto 是一个简单的类(在 ABP 中定义),用于传递下拉框 Combobox 的项目的数据。 TaskController.Create 方法仅使用了这个方法并将返回的列表转换为 SelectListItem (在 AspNet Core 中定义),然后用 CreateTaskViewModel 返回给视图。

代码如下

using System.Collections.Generic;

using Microsoft.AspNetCore.Mvc.Rendering;


namespace Acme.SimpleTaskApp.Web.Models.People

{

    public class CreateTaskViewModel

    {

        public List&lt;SelectListItem> People { get; set; }


        public CreateTaskViewModel(List&lt;SelectListItem> people)

        {

            People = people;

        }

    }

}

Create 视图如下:

代码如下

@using Acme.SimpleTaskApp.Web.Models.People

@model CreateTaskViewModel


@section scripts

{

    &lt;environment names="Development">

        &lt;script src="~/js/views/tasks/create.js">&lt;/script>

    &lt;/environment>


    &lt;environment names="Staging,Production">

        &lt;script src="~/js/views/tasks/create.min.js">&lt;/script>

    &lt;/environment>

}


&lt;h2>

    @L("NewTask")

&lt;/h2>


&lt;form id="TaskCreationForm">

    

    &lt;div class="form-group">

        &lt;label for="Title">@L("Title")&lt;/label>

        &lt;input type="text" name="Title" class="form-control" placeholder="@L("Title")" required maxlength="@Acme.SimpleTaskApp.Tasks.Task.MaxTitleLength">

    &lt;/div>


    &lt;div class="form-group">

        &lt;label for="Description">@L("Description")&lt;/label>

        &lt;input type="text" name="Description" class="form-control" placeholder="@L("Description")" maxlength="@Acme.SimpleTaskApp.Tasks.Task.MaxDescriptionLength">

    &lt;/div>


    &lt;div class="form-group">

        @Html.Label(L("AssignedPerson"))

        @Html.DropDownList(

            "AssignedPersonId",

            Model.People,

            new

            {

                @class = "form-control",

                id = "AssignedPersonCombobox"

            })

    &lt;/div>


    &lt;button type="submit" class="btn btn-default">@L("Save")&lt;/button>


&lt;/form>

我们编写 create.js 如下:

代码如下

(function($) {

    $(function() {


        var _$form = $('#TaskCreationForm');


        _$form.find('input:first').focus();


        _$form.validate();


        _$form.find('button[type=submit]')

            .click(function(e) {

                e.preventDefault();


                if (!_$form.valid()) {

                    return;

                }


                var input = _$form.serializeFormToObject();

                abp.services.app.task.create(input)

                    .done(function() {

                        location.href = '/Tasks';

                    });

            });

    });

})(jQuery);

让我们一起来看看这个 javascript 代码都做了什么:

  • 在表单里预先做好验证(使用 jquery validation 插件)准备,并在保存 Save 按钮被点击后进行验证。

  • 使用序列化表格为对象 serializeFormToObject 插件 (在解决方案中的 jquery-extensions.js 中定义), 将表格数据 forum data 转换为 JSON 对象(我们将 jquery-extensions.js 添加到最后的脚本文件 _Layout.cshtml )

  • 使用 abp.services.task.create 方法调用 TaskAppService.Create 方法。这是 ABP 中的一个很重要的特性。我们可以在 javascript 代码中使用应用服务,简单的就想在代码里直接调用 javascript 方法 (详情请见  details)

最后,我们在任务列表页面里添加一个 “添加任务 Add Task”按钮,点击后就可以导航到任务创建页面:

代码如下

1 &lt;a class="btn btn-primary btn-sm" asp-action="Create">@L("AddNew")&lt;/a>

删除主页和关于页

如果我们不需要主页和关于页,我们可以从应用里删除掉它们。首先,删除主页控制器 HomeController :

代码如下

using Microsoft.AspNetCore.Mvc;


namespace Acme.SimpleTaskApp.Web.Controllers

{

    public class HomeController : SimpleTaskAppControllerBase

    {

        public ActionResult Index()

        {

            return RedirectToAction("Index", "Tasks");

        }

    }

}

然后删除 视图里的主页 Views/Home 文件夹并从 SimpleTaskAppNavigationProvider 类里删除菜单项。我们也可以从本地化 JSON 文件中删除点不需要的关键词。

 

其他相关内容

我们将不断改进本篇内容

  • 从任务列表里打开/关闭任务,然后刷新任务项目。

  • 为责任人下拉框使用组件

  • 等等

 

文章更改历史

  • 2017-07-30:将文章中的 ListResultOutput 替换为 ListResultDto

  • 2017-06-02:将项目和文章修改为支持 .net core

  • 2016-08-09:根据反馈修改文章

  • 2016-08-08:初次发布文章

相关文章:

  • 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)

  • ABP .Net Core Entity Framework迁移使用MySql数据库

  • [52ABP实战系列] .NET CORE实战入门第三章更新了

  • ABP从入门到精通(1):aspnet-zero-core项目启动及各项目源码说明

  • ABP从入门到精通(2):aspnet-zero-core 使用MySql数据库

  • ABP从入门到精通(3):aspnet-zero-core 使用Redis缓存

  • ABP从入门到精通(4):使用基于JWT标准的Token访问WebApi

  • ABP从入门到精通(5):.扩展国际化语言资源

原文地址:http://www.cnblogs.com/yabu007/p/8117792.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘微软6万工程师DevOps成功转型的技术「武器」

在微软&#xff0c;通过其自身数年的 DevOps 转型&#xff0c; 6 万名工程师实现了更好的软件平台创新和快速迭代。微软有庞大的技术产品矩阵&#xff0c;同时也具有每天发布的能力&#xff0c;其中&#xff0c;微软研发云是支撑整个开发过程与运维最重要的基础平台。微软研发云…

Flowable学习笔记(一、入门)

转载自 Flowable学习笔记&#xff08;一、入门&#xff09; 一、Flowable简介 1、Flowable是什么 Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义&#xff08;用于定义流程的行业XML标准&#xff09;&#xff0c; 创建这些流…

01-MyBatis入门程序

MyBatis入门程序 目录 1. 下载 Mybatis 核心包2. 创建工程&#xff0c;引入 MyBatis 核心包及依赖包3. 创建 customer 表&#xff0c;建立与表对应的 domain使用 lombok&#xff0c;开启注解创建 Customer 类4. 创建 MyBatis 核心配置文件 SqlMappingConfig.xml5. 创建表对象…

角落的开发工具集之Vs(Visual Studio)2017插件推荐

“ 工具善其事&#xff0c;必先利其器&#xff01;装好这些插件让vs更上一层楼”因为最近录制视频的缘故&#xff0c;很多朋友都在QQ群留言&#xff0c;或者微信公众号私信我&#xff0c;问我一些工具和一些插件啊&#xff0c;怎么使用的啊&#xff1f;那么今天我忙里偷闲整理一…

02-MyBatis配置SQL打印

MyBatis 配置SQL打印 在 SqlMappingConfig.xml 中配置以下代码&#xff1a; <!--配置sql打印--> <settings><setting name"logImpl" value"STDOUT_LOGGING"/> </settings>运行效果&#xff1a;会显示 SQL 语句&#xff0c;查询结…

Flowable学习笔记(二、BPMN 2.0-基础 )

转载自 Flowable学习笔记&#xff08;二、BPMN 2.0-基础 &#xff09; 1、BPMN简介 业务流程模型和标记法&#xff08;BPMN, Business Process Model and Notation&#xff09;是一套图形化表示法&#xff0c;用于以业务流程模型详细说明各种业务流程。 它最初由业务流程管理…

ASP.NET Core文件上传与下载(多种上传方式)

前言前段时间项目上线,实在太忙,最近终于开始可以研究研究ASP.NET Core了.打算写个系列,但是还没想好目录,今天先来一篇,后面在整理吧.ASP.NET Core 2.0 发展到现在,已经很成熟了.下个项目争取使用吧.正文1.使用模型绑定上传文件(官方例子)官方机器翻译的地址:https://docs.mic…

03-映射文件的sql语句中 #{} 和 ${} 的区别以及实现模糊查询

映射文件的sql语句中 #{} 和 ${} 区别以及实现模糊查询 目录 sql 语句中的 #{}#{} 模糊查询错误用法#{} 实现模糊查询sql 语句中的 ${}${} 实现模糊查询#{} 与 ${} 对比sql 语句中的 #{} 表示一个占位符号&#xff0c;通过 #{} 可以实现 preparedStatement 向占位符中设置值…

SpringBoot集成Flowable

一、项目结构 二、maven配置 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.a…

04-插入操作更新操作删除操作

保存更新删除 目录 插入操作获取插入的最后一个id更新操作删除操作插入操作 映射文件 Customer.xml &#xff1a; 插入数据的标签为 insert&#xff0c;与查询 select 区分开来。 parameterType 是输入参数类型&#xff0c;这里指定为 Customer 对象&#xff0c;即需要传入一…

微软跨平台移动开发工具套件HockeyApp宣布免费

HockeyApp 是一款领先的移动崩溃分析和应用发布服务&#xff0c;可为开发者提供实时崩溃分析报告、用户反馈、测试版分发平台以及测试分析等功能&#xff0c;于 2016 年被微软收购&#xff0c;随后集成在了 Visual Studio 应用中心中&#xff0c;与 Xamarin Insights 一起提供移…

ASP.NET Core使用静态文件、目录游览与MIME类型管理

前言今天我们来了解了解ASP.NET Core中的静态文件的处理方式.以前我们寄宿在IIS中的时候,很多静态文件的过滤 和相关的安全措施 都已经帮我们处理好了.ASP.NET Core则不同,因为是跨平台的,解耦了IIS,所以这些工作 我们可以在管道代码中处理.正文在我们的Web程序开发中,肯定要提…

ES快速入门

转载自 ES快速入门 3 ES快速入门 ES作为一个索引及搜索服务&#xff0c;对外提供丰富的REST接口&#xff0c;快速入门部分的实例使用head插件来测试&#xff0c;目的是对ES的使用方法及流程有个初步的认识。 3.1 创建索引库 ES的索引库是一个逻辑概念&#xff0c;它包括了分…

05-传统开发模式DAO

传统开发模式DAO 目录 定义接口 CustomerDao.java实现接口 CustomerDaoImpl.java测试类在传统开发模式DAO下&#xff0c;我们自己先定义好接口&#xff0c;然后再去定义实现类&#xff0c;在实现类中实现接口的操作。到时候只需要创建一个 dao 对象&#xff0c;即可调用其中的…

AspnetCore 2.0 自动API文档生成组件,支持protobuffer

关于API文档自动生成&#xff0c;用于对APP端的开发帮助文档生成&#xff0c;默认ProtoBuffer传输格式。本项目并不是RESTful风格&#xff0c;是面向功能的API类型。ApiDoc的作用是根据定义好的API接口和注释来自动生成给内部开发者提供的API对接文档。欢迎Star一下&#xff0c…

06-Mapper动态代理

Mppaer 动态代理 目录 创建 Mapper 工程定义接口的要求测试类Mapper 中参数传递单个参数多个参数param命名参数多个参数封装成 Map多个参数之 POJO参数处理源码分析之前我们一直都使用传统开发模式DAO&#xff0c;即定义接口&#xff0c;然后定义实现类。这个其实是较为繁琐的…

ASP.NET Core MVC中的 [Required]与[BindRequired]

在开发ASP.NET Core MVC应用程序时&#xff0c;需要对控制器中的模型校验数据有效性&#xff0c;元数据注释(Data Annotations)是一个完美的解决方案。元数据注释最典型例子是确保API的调用者提供了某个属性的值&#xff0c;在传统的ASP.NET MVC中使用的是RequiredAttribute特性…

ES集群管理

转载自 ES集群管理 8 集群管理 ES通常以集群方式工作&#xff0c;这样做不仅能够提高 ES的搜索能力还可以处理大数据搜索的能力&#xff0c;同时也增加了系统的容错能力及高可用&#xff0c;ES可以实现PB级数据的搜索。 下图是ES集群结构的示意图&#xff1a; 从上图总结以下…

【Java探索之旅】我与Java的初相识(完):注释,标识符,关键字

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java入门到精通 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. Java的注释方式二. 标识符三. 关键字四. 全篇总结 &#x1f4d1;前言 在Java编程…

07-MyBatis 核心配置文件

MyBatis 核心配置文件 目录 properties 定义属性及读取属性文件settings 设置运行时行为typeAliases 类型别名定义单个别名批量定义别名typeHandlers 类型处理器Plugins&#xff08;后续有文章专门介绍这个&#xff09;Environments 运行环境databaseIDProvider 定义数据库厂…