皇冠体育寻求亚洲战略合作伙伴,皇冠代理招募中,皇冠平台开放会员注册、充值、提现、电脑版下载、APP下载。

首页快讯正文

usdt手机钱包(www.caibao.it):《进击吧!Blazor!》第一章 4.数据交互

admin2021-03-0225

USDT第三方支付平台

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

原题目:《进击吧!Blazor!》第一章 4.数据交互

作者:陈超超

Ant Design Blazor 项目贡献者,拥有十多年从业履历,历久基于.Net手艺栈举行架构与开发产物的事情,现就职于正泰团体。

邮箱:timchen@live.com

迎接列位读者有任何问题联系我,我们共同进步。

上一次课程我们完成了ToDo应用的界面制作,这次我们要将客户端的数据写入数据库,并从数据库中读取我们需要的数据。

数据交互历程

我们先看一下从客户端到数据库的流程

Blazor

Blazor客户端就是我们上节课做的ToDo程序。

HttpClient

HttpClient就是我们完成 *** 通讯用的组件,对于这类组件我们希望在一个应用中只组织一次,这样制止重复分配资源,因此我们在 Program.cs 中举行注册。

{

{

builder.Services.AddScoped(sp => HttpClient { BaseAddress = Uri(builder.HostEnvironment.BaseAddress) });

}

}

BaseAddress 为基地址,这样我们使用时,Url只需要传入相对地址即可,此处默以为当前主机的地址。

DefaultRequestHeaders 默认HTTP请求头参数

Timeout 毗邻超时参数

上面通过服务注入的方式实现了 HttpClient 全局共享(单例),那么若何使用服务?这里我们就需要引入一下“依赖关系注入 (DI)”的观点。

DI是一种手艺,基本原理是把有依赖关系的类放到容器中,解析出这些类的实例,就是依赖注入。应用可通过将内置服务注入组件来使用这些服务。应用还可界说和注册自界说服务,并通过 DI 使其在整个应用中可用。

该手艺在 Blazor 应用中常用于以下两个方面:

服务生存期决议了服务何时建立,何时销毁,有三种模式:

Scoped : Blazor WebAssembly 应用当前没有 DI 局限的观点。已注册 Scoped 的服务的行为与 Singleton 服务类似。然则,Blazor Server 托管模子支持 Scoped 生存期。在 Blazor Server 应用中, Scoped 服务注册的局限为“毗邻”。因此,纵然当前意图是在浏览器中运行客户端,对于局限应限定为当前用户的服务来说,首选使用 Scoped 服务。

Singleton :DI 建立服务的单个实例。需要 Singleton 服务的所有组件都市吸收统一服务的实例。

Transient :每当组件从服务容器获取 Transient 服务的实例时,它都市吸收该服务的新实例。

这里的 HttpClient 使用了 AddScoped 方式,那么就是当前局限内使用统一个实例,由于项目是 Blazor WebAssembly 模式,以是相当于单例服务。

ASP.Net Core

我用ASP.Net Core项目给Blazor应用提供WebAPI接口

官方文档:https://docs.microsoft.com/zh-cn/aspnet/core

项目结构如下

这里设置了我们调试的方式,端口等,相对于通俗的Web项目多了 inspectUri 属性,具有以下作用:

  1. 使 IDE 能够检测到该应用为 Blazor WebAssembly 应用。
  2. 指示剧本调试基础结构通过 Blazor 的调试署理毗邻到浏览器。
  3. 已启动的浏览器 (browserInspectUri) 上 WebSocket 协议 (wsProtocol)、主机 (url.hostname)、端口 (url.port) 和检查器 URI 的占位符值由框架提供。
{

: {

: {

: ,

: ,

: ,

: {

:

}

},

}

  • Controllers

控制器( Controller )放在这里,站点的路由表是通过遍历项目中带有 ApiControllerAttribute (基类 ControllerAttribute )的类,然后寻找内里的方式实现,他和Blazor的路由表建立方式上有点相似。

[ ]

[ ]

:

Route 界说了路由花样,上例中 [controller]/[action] 意为使用 Controller 和 action 的名称作为路由地址,这样写可以省去每个 action 上符号路由名字的贫苦。

  • Pages

存放页面文件的位置,由于我们的项目页面所有使用Blazor构建,以是用不到此文件夹,因此这里就不做先容了。

  • appsettings.json

站点的设置文件,我们的项目就用到了数据库链接字符串设置

  • Program.cs

应用的 Main 函数在这里,这里完成了 Host 的建立与启动

  • Startup.cs

启动类,项目启动时的服务注册,设置等事情都在此处完成

ConfigureServices 使用此方式将服务添加到容器。

Configure 使用此方式来设置HTTP请求管道。

{

app.UseBlazorFrameworkFiles;

app.UseStaticFiles;

app.UseRouting;

app.UseEndpoints(endpoints =>

{

endpoints.MapRazorPages;

endpoints.MapControllers;

endpoints.MapFallbackToFile( );

});

}

app.UseBlazorFrameworkFiles; 设置应用程序提供Blazor WebAssembly框架文件,默认根路径为 / ,也可以自界说路径前缀

endpoints.MapControllers; 添加控制器( Controller )的路由。

endpoints.MapFallbackToFile("index.html"); 添加默认路由地址是 index.html 。

EF Code

所有的数据我们需要保留入数据库,这里我选择使用EF Core作为我们的数据接见手艺

官方文档:https://docs.microsoft.com/zh-cn/ef/

EF Core部门特点

  • Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的数据接见手艺。
  • EF Core可用作工具关系映射程序 (O/RM),能让我们用工具来处置数据库,使用Linq举行查询,这样我们就可以不用编写大量SQL代码了。
  • EF Core 支持多个数据库引擎,好比MySQL、SQLite等。

他支持接纳Code Firs或者Database First两种模式

  • Code Firs 用代码编写工具关系,然后通过它建立数据库。
  • Database First 可以提供现有数据库,反向天生工具映射 。

Database

数据库我选择SQL Server,使用 *** 微软手艺栈工具链使用体验比较好,固然我们也可以选择其他数据库。

SQL Server产物家族中有一个SQL Server LocalDB的器械,它是SQL Server的一个超级精简版本,安装包只有几十MB(安装好后200+MB),它包含了数据库的基础功效,然则不支持联网,只能本机毗邻,对于小我私家开发资源占用少,强烈推荐,VS安装Web开发组件会默认安装此数据库。

毗邻时服务器名称默认是 (localdb)MSSQLLocalDB ,也可以使用 C:Program FilesMicrosoft SQL Server130ToolsBinnSqlLocalDB.exe 举行设置数据库实例

我们可以使用VS的SQL Server工具资源管理器来查看我们的数据库,不外我这里强烈推荐使用SQL Server Management Studio (S *** S) 的“数据库关系图”功效来维护数据库,可视化编辑表,主外键关系等,保留即更新数据库,这对于数据库优先的模式下开发异常友好,效率极高。

下图是我们ToDo应用使用的表结构。

代码实战

上面先容了数据交互的流程观点,接下来我们革新上回制作的ToDo项目。

引入和设置EF Code

我们先建立一个 ToDo.Entity 项目用于存储ORM映射以及EF的Context。

注重:现在VS 16.8.4版本建立类库会默认使用.net core 3.1,需要手动修改成.net 5

使用EF Core Power Tools工具建立代码

由于我们上面已经把数据库设计完成了,以是我们接纳 Database First 模式建立EF相关的代码。

此处推荐一个从数据库到EF实体的代码天生扩展 EF Core Power Tools

扩展下载地址:https://marketplace.visualstudio.com/items?itemName=ErikEJ.EFCorePowerTools

选摘要毗邻的数据库。

选摘要添加的数据库工具。

设置 Context 的名称和命名空间等,下图是我常用设置。

EF Core Power Tools 天生的代码文件如下

appsettings.json中添加链接字符串

打开 ToDo.Serverappsettings.json 添加数据库毗邻字符串

: {

:

},

使用 EF Core Power Tools 天生的 TodoContext.cs 文件中就有默认的毗邻字符串,开发时想偷懒可以直接从这里复制。

ConfigureServices中添加服务注册

打开 ToDo.ServerStartup.cs ,把 TodoContext 注册到 DbContext 中为,并设置毗邻字符串

services.AddDbContext<TodoContext>(options =>

{

options.UseSqlServer(Configuration.GetConnectionString( ));

});

有时候我们需要在输出EF执行的SQL语句,这便于我们调试以及优化数据库,下面的设置就把EF日志输出到控制台

ILoggerFactory loggerFactory = LoggerFactory.Create(builder => { builder.AddConsole; });

{

services.AddDbContext<TodoContext>(options =>

{

options.UseSqlServer(Configuration.GetConnectionString( )).UseLoggerFactory(loggerFactory);

});

}

功效实现

首先建立 ToDo.ServerControllersTaskController.cs 文件用于编写WebAPI接口,代码如下:

{

[ ]

[ ]

:

{

TodoContext Context;

{

Context = context;

}

}

}

通过依赖注入将 TodoContext 注入到当前类中。

1. 列出当天的所有代庖事情

ToDo.Server

TaskController.cs 中添加 GetToDayTask 方式用于返回当前待办数据。

[ ]

{

result = Context.Task.Where(x => x.PlanTime == DateTime.Now.Date);

QueryToDto(result).ToList;

}

[ ]

{

query.Select(x => TaskDto

{

TaskId = x.TaskId,

Title = x.Title,

Deion = x.Deion,

PlanTime = x.PlanTime,

Deadline = x.Deadline,

IsImportant = x.IsImportant,

IsFinish = x.IsFinish,

});

}

ToDo.Client

添加 PagesToDay.razor.cs 类文件,VS会自动将 ToDay.razor 与 ToDay.razor.cs 折叠到一起。

在类界说中增添 partial 关键字,声明类为局部类,你可以明白成 ToDay.razor 与 ToDay.razor.cs 中的代码都属于统一个类,只是放在差别文件中,编译器编译时会将他们合并到一起后举行编译。

接着做一下代码迁徙

  1. 将 PagesToDay.razor 文件 @code{} 中的代码剪切到 ToDay.razor.cs
  2. 将 PagesToDay.razor 文件 @inject 代码接纳 [Inject] public MessageService MsgSrv { get; set; } 这样的花样等价的迁徙到 ToDay.razor.cs

这样做我们可以实现界面代码与营业代码分开在差别的文件中,利便整理代码,提高代码可读性。

后续其他页面我默认完成了建立局部类的操作,不再赘述。

ToDay.razor.cs 中添加 HttpClient 的依赖注入,用于向服务端提议Http请求

[ ] HttpClient Http { ; ; }

项目中其他类若是使用到 HttpClient ,我默认完成了依赖注入,不再赘述。

广告时间

Blazor 和 Ant Design Blazor 中有许多服务,我们经常在差别的地方需要注入,为了编码利便,我们提供了一个VS扩展快速插入常用服务代码段,安装地址:https://marketplace.visualstudio.com/items?itemName=TimChen44.AntDesignBlazorSnippets

修改 OnInitializedAsync 方式的代码

= List<TaskDto>;

isLoading = ;

{

isLoading = ;

taskDtos = Http.GetFromJsonAsync<List<TaskDto>>( );

isLoading = ;

.OnInitializedAsync;

}

Http.GetFromJsonAsync<List<TaskDto>> 使用 HttpGet 模式请求数据,这里使用 await 举行异步守候,充分利用 await 可以极大的简化代码量。

isLoading 是载入状态, *** 通讯肯定有延迟,制止白屏,我们在载入前后划分改变载入状态,同时修改 ToDay.razor 代码添加 Spin 组件用于显示载入效果。

@foreach (var item in taskDtos)

2. 添加代庖

ToDo.Server

TaskController.cs 中添加 SaveTask 方式用于保留新的待办内容

[ ]

{

Entity.Task entity;

(dto.TaskId == Guid.Empty)

{

entity = Entity.Task;

entity.TaskId = Guid.NewGuid;

Context.Add(entity);

}

{

entity = Context.Task.FirstOrDefault(x => x.TaskId == dto.TaskId);

}

entity.Title = dto.Title;

entity.Deion = dto.Deion;

entity.PlanTime = dto.PlanTime;

entity.Deadline = dto.Deadline;

entity.IsImportant = dto.IsImportant;

entity.IsFinish = dto.IsFinish;

Context.SaveChanges;

entity.TaskId;

}

我通过判断 dto.TaskId 的值,直接将新增与更新写在一个接口中,这样可以复用代码。

此处可以使用 AutoMapper 库来简化赋值历程,这将在未来的章节中详细先容

ToDo.Client

ToDay.razor.cs 文件修改 OnInsert 方式相关的代码

TaskDto newTask = TaskDto { PlanTime = DateTime.Now.Date };

[ ] MessageService MsgSrv { ; ; }

isNewLoading = ;

{

(e.Code == )

{

( .IsNullOrWhiteSpace(newTask.Title))

{

MsgSrv.Error( );

;

}

isNewLoading = ;

result = Http.PostAsJsonAsync<TaskDto>( , newTask);

(result.IsSuccessStatusCode)

{

newTask.TaskId = result.Content.ReadFromJsonAsync<Guid>;

taskDtos.Add(newTask);

newTask = TaskDto { PlanTime = DateTime.Now.Date };

}

{

MsgSrv.Error( );

}

isNewLoading = ;

StateHasChanged;

}

}

ToDay.razor 文件增添保留时守候组件

通过 Http.PostAsJsonAsync 挪用 api/Task/SaveTask 将 newTask 内容提交到后端并保留,返回的 HttpResponseMessage 包含了状态编码等,若是乐成就在界面上显示新的待办,失败就提醒错误

MessageService 全局展示操作反馈信息。

组件文档地址:https://ant-design-blazor.github.io/zh-CN/components/message

3. 编辑待办

ToDo.Server

TaskController.cs 中添加 GetTaskDto 方式用于获取待办信息

{

result = Context.Task.Where(x => x.TaskId == taskId);

QueryToDto(result).FirstOrDefault;

}

ToDo.Client

TaskInfo.razor 文件中增添 Spin 与 @if 代码

@if (taskDto != null)

{

,

usdt收款平台

菜宝钱包(caibao.it)是使用TRC-20协议的Usdt第三方支付平台,Usdt收款平台、Usdt自动充提平台、usdt跑分平台。免费提供入金通道、Usdt钱包支付接口、Usdt自动充值接口、Usdt无需实名寄售回收。菜宝Usdt钱包一键生成Usdt钱包、一键调用API接口、一键无实名出售Usdt。

,

保留

作废

}

TaskInfo.razor.cs 添加下面代码

: < , >

{

[ ]

HttpClient Http { ; ; }

[ ]

MessageService MsgSvr { ; ; }

TaskDto taskDto;

isLoading = ;

{

taskDto = Http.GetFromJsonAsync<TaskDto>( );

.OnInitializedAsync;

}

{

result = Http.PostAsJsonAsync<TaskDto>( , taskDto);

(result.StatusCode == System.Net.HttpStatusCode.OK)

{

.CloseAsync(taskDto);

}

{

MsgSvr.Error( );

}

}

{

.CloseAsync( );

}

}

ToDay.razor.cs 中的 OnCardClick 方式更新

[ ] DrawerService DrawerSrv { ; ; }

{

result = DrawerSrv.CreateDialogAsync<TaskInfo, TaskDto, TaskDto>(task, title: task.Title, width: );

(result == ) ;

index = taskDtos.FindIndex(x => x.TaskId == result.TaskId);

taskDtos[index] = result;

InvokeAsync(StateHasChanged);

}

DrawerSrv.CreateDialogAsync 相对于 DrawerSrv.CreateAsync 简化了挪用方式,默认将抽屉的 CloseAsync 参数返回,这就简化了每次使用抽屉时需要注册 CloseAsync 事宜的贫苦,也让代码加倍清晰。

title: task.Title, width: 450 使用可选参数简化对抽屉的参数设置。

DrawerService组件辅助文档:https://ant-design-blazor.github.io/zh-CN/components/drawer

4. 修改主要水平

ToDo.Server

TaskController.cs 中添加 SetImportant 方式用于修改 IsImportant 字段的值

[ ]

{

entity = Context.Task.FirstOrDefault(x => x.TaskId == req.TaskId);

entity.IsImportant = req.IsImportant;

Context.SaveChanges;

}

ToDo.Shared

添加 SetImportantReq 类用于 SetImportant 接口请求参数

{

Guid TaskId { ; ; }

IsImportant { ; ; }

}

ToDo.Client

ToDay.razor.cs 中的 OnStar 方式更新

{

req = SetImportantReq

{

TaskId = task.TaskId,

IsImportant = !task.IsImportant,

};

result = Http.PostAsJsonAsync<SetImportantReq>( , req);

(result.IsSuccessStatusCode)

{

task.IsImportant = req.IsImportant;

StateHasChanged;

}

}

5. 修改完成状态

ToDo.Server

TaskController.cs 中添加 SetFinish 方式用于修改 IsFinish 字段的值

[ ]

{

entity = Context.Task.FirstOrDefault(x => x.TaskId == req.TaskId);

entity.IsFinish = req.IsFinish;

Context.SaveChanges;

}

ToDo.Shared

添加 SetFinishReq 类用于 SetFinish 接口请求参数

{

Guid TaskId { ; ; }

IsFinish { ; ; }

}

ToDo.Client

ToDay.razor.cs 中的 OnFinish 方式更新

{

req = SetFinishReq

{

TaskId = task.TaskId,

IsFinish = !task.IsFinish,

};

result = Http.PostAsJsonAsync<SetFinishReq>( , req);

(result.IsSuccessStatusCode)

{

task.IsFinish = req.IsFinish;

StateHasChanged;

}

}

6. 删除代庖

ToDo.Server

TaskController.cs 中添加 DelTask 方式用于删除待办。

[ ]

{

Context.Task.Remove(Context.Task.Find(taskId));

Context.SaveChanges;

}

ToDo.Client

ToDay.razor.cs 中的 OnFinish 方式更新

[ ] ConfirmService ConfirmSrv { ; ; }

{

( ConfirmSrv.Show( , , ConfirmButtons.YesNo, ConfirmIcon.Info) == ConfirmResult.Yes)

{

taskDtos.Remove(task);

}

}

ConfirmService 可以快捷地弹出一个内置的确认框,类似于 Windows MessageBox。

ConfirmService组件辅助文档:https://ant-design-blazor.github.io/zh-CN/components/modal

7. 查询代庖

ToDo.Server

TaskController.cs 中添加 GetSearch 方式用于修改 SetFinish 字段的值

[ ]

{

(req.PageIndex == ) req.PageIndex = ;

query = Context.Task.Where(x => x.Title.Contains(req.QueryTitle ?? ));

( sort req.Sorts)

{

(sort.SortOrder == )

query = query.OrderBy(sort.SortField + );

query = query.OrderBy(sort.SortField);

}

result = GetSearchRsp

{

Data = QueryToDto(query.Skip(--req.PageIndex * req.PageSize).Take(req.PageSize)).ToList,

Total = query.Count,

};

result;

}

if (req.PageIndex == 0) req.PageIndex = 1 吐槽更先:险些所有的UI框架页码都是从0更先,然则AntDesign规范的页码是从1更先的,然而没有载入数据时又是返回0,以是要特别注重。

OrderBy 使用了 System.Linq.Dynamic.Core 扩展包,它提供了一些动态的Linq支持,好比此处排序我传入的参数不是一个表达式,而是一个字符串,这样可以让代码灵活性大增。

ToDo.Shared

{

QueryTitle { ; ; }

PageIndex { ; ; }

PageSize { ; ; }

List<SortFieldName> Sorts { ; ; }

}

{

SortField { ; ; }

SortOrder { ; ; }

}

{

List<TaskDto> Data { ; ; }

Total { ; ; }

}

ToDo.Client

TaskSearch.razor 文件的代码

@page "/search"

@context.Title

@if (context.IsImportant)

{

主要

}

@if (context.IsFinish)

{

}

TaskSearch.razor.cs 文件的代码

[ ] HttpClient Http { ; ; }

isLoading = ;

List<TaskDto> datas = List<TaskDto>;

queryTitle;

total = ;

{

OnQuery( , , List<SortFieldName>);

}

{

OnQuery(

queryModel.PageIndex,

queryModel.PageSize,

queryModel.SortModel.Where(x => .IsNullOrEmpty(x.SortType.Name) == ).OrderBy(x => x.Priority)

.Select(x => SortFieldName { SortField = x.FieldName, SortOrder = x.SortType.Name }).ToList

);

}

{

isLoading = ;

req = GetSearchReq

{

QueryTitle = queryTitle,

PageIndex = pageIndex,

PageSize = pageSize,

Sorts = sort,

};

httpRsp = Http.PostAsJsonAsync<GetSearchReq>( , req);

result = httpRsp.Content.ReadFromJsonAsync<GetSearchRsp>;

datas = result.Data;

total = result.Total;

isLoading = ;

}

Search 带有查询按钮的文本框框

Search组件文档地址:https://ant-design-blazor.github.io/zh-CN/components/input

查看详细服务

在 我的一天 与 所有 页面上均存在打开待办详情的功效需求,这时我们就可以自己做一个服务将双方的功效合并到一起。

添加 TaskDetailServices.cs 文件,加入以下代码

{

{

DrawerService DrawerSvr { ; ; }

{

DrawerSvr = drawerSvr;

}

{

taskItem = DrawerSvr.CreateDialogAsync<TaskInfo, TaskDto, TaskDto>(taskDto, title: taskDto.Title, width: );

(taskItem == ) ;

index = datas.FindIndex(x => x.TaskId == taskItem.TaskId);

datas[index] = taskItem;

}

}

}

TaskDetailServices(DrawerService drawerSvr) 只有 razor 文件可以使用 [Inject] 符号属性举行注入服务,通俗得类需要在组织函数中界说才气注入服务。

Program.cs 文件中注册 TaskDetailServices

builder.Services.AddScoped<TaskDetailServices>;

TaskSearch.razor 文件中添加详情按钮

详情

TaskSearch.razor.cs 插入以下代码,我们注入自界说的服务,使用服务中的方式打开编辑界面。

[ ] TaskDetailServices TaskSrv { ; ; }

{

TaskSrv.EditTask(taskDto, datas);

}

次回预告

网友评论