|
|
6 G: Y1 _. X0 F& a
<h2 id="系列导航">系列导航</h2> V5 |- H7 V: a7 H
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
' {* N. U0 v6 c; H) k6 T7 `8 {/ M3 @<h2 id="需求">需求</h2>
0 W: y9 K7 V$ Y% l5 X f! n+ h<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
d% l4 O, c$ }0 v5 z6 k: O<h2 id="思路">思路</h2>
& Q4 N5 N& v" |<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>0 F" |' c7 a% r1 {% r$ [
<h2 id="实现">实现</h2>
. B I3 c% N1 `, v& N+ G; G2 i4 x2 U$ c<p>为了保持简单,我们先定义以下两个类型:</p>
' Z- Y( X/ {0 k( d$ v<pre><code class="language-c#">// 定义新增Post的参数
/ |: l. S; Y+ G4 g8 T5 Lpublic record AddPostInput(string Title, string Author);
' \' J/ v1 S/ c J, a6 h
# J: G( {; B" M1 g! W// 定义新增Post的返回对象
5 Z8 q1 l; T; i' [8 ?. Jpublic record AddPostPayload(Post Post);' ]0 v0 f& j- p$ S) ^
</code></pre>1 E/ T# B6 i+ \$ C! N
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
$ x+ v. n3 G& I* v) `8 C<ul>3 @$ _8 X! R, g) C5 }
<li><code>Mutation.cs</code></li>
; R' b% X8 b) E1 }, }! G( l</ul>6 t8 k6 V( F2 N. T( l* H7 m- l
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;& N. Z: F' O, |, \2 C
6 M* g- j3 Y- a0 T& zpublic class Mutation8 z. _5 O- s9 b {5 x* ^- T
{
& J% u7 u7 W* ~& f- L& `4 D public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
6 T$ c! H7 _. B# m6 U) u+ h- E/ d {
$ N) D! ?0 [. g4 `7 |4 Y return new AddPostPayload(await repository.AddAsync(new Post
% D& K) V6 g" W, N+ s6 n6 b {& U! Q' i( b- {5 D
Title = input.Title,
) S" v+ j: r2 j& n: [4 r, ^ Author = input.Author5 M! W5 n; z$ R! q
}));
# O: l7 a; n+ r, E; j$ o+ u# S }
4 D, n" n k. j6 m2 z}
- }, z) R r2 W! {* P& [3 P$ ]/ O7 T: c$ m
</code></pre>) ?" j" n2 q# b" Z
<p>最后在注入服务的地方进行配置:</p>
" V0 P) A9 ~7 H6 c2 N<ul>
! {/ {& C- y. ?3 h. P4 s<li><code>ProgramExtensions.cs</code></li># b4 D, u% h$ _' _
</ul>/ E) ]6 v; ^6 f6 s! {( `
<pre><code class="language-c#">builder.Services
# ~) N& m3 G, E9 _ .AddGraphQLServer()3 ~. c3 N, o) {, Z6 c( i- p' |" Y
.SetPagingOptions(new PagingOptions6 P$ F9 p! m+ F5 N7 K
{
, [$ b6 {- G5 T' p8 z H MaxPageSize = 50,
' }9 D; C" J R" F5 L, \7 _6 k4 z IncludeTotalCount = true) I! |7 i, d" G: o z
})
7 L3 o( k4 Q) R$ d .AddFiltering()
4 y' L/ q) q, a" c* p) B7 }* Q9 r .AddProjections()
. s5 Q5 f( W, z& J& S" K .AddSorting()
8 ?" J5 V( O7 ]) R5 ]$ Y .AddQueryType<Query>()& h) D4 q/ A- p1 E$ g9 e
.AddMutationType<Mutation>()
. J* d J4 C: G8 k4 I .AddMutationConventions(new MutationConventionOptions+ e7 N* s+ @9 f' p
{
! r. l% P G9 K3 @7 M9 P6 E, d ApplyToAllMutations = true,
. f0 o9 F& e9 i InputArgumentName = "input",
9 x* R: h3 U: D InputTypeNamePattern = "{MutationName}Input",1 o1 |$ N; T9 F* q0 F' c) t
PayloadTypeNamePattern = "{MutationName}Payload",
5 y- G) o+ q$ U+ r PayloadErrorTypeNamePattern = "{MutationName}Error",# ^; H% p% G5 j$ C* P
PayloadErrorsFieldName = "errors"
% ~# f2 i/ i x5 [ })
, T3 E2 |, v; r$ I. l4 B .AddType<PostType>();; G* A& T' b" d. N! v
</code></pre>/ K. D. G8 k3 e. e
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
/ a K' }7 Q( ^ z( w4 K<h2 id="验证">验证</h2>
# U4 o) q3 ] i, Y0 d2 k' g5 C<p>启动<code>Api</code>项目,调用接口:</p>
* s. [5 E8 A& Y% v<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
" A# u$ F- l" P/ I<p>终端的日志输出如下:</p>
! e1 o! }" j4 ]7 s. t9 h<pre><code class="language-bash">[10:45:15 INF] Executed DbCommand (1ms) [Parameters=[@p0='?' (DbType = Guid), @p1='?', @p2='?' (Size = 13), @p3='?', @p4='?' (DbType = DateTime), @p5='?', @p6='?' (DbType = DateTime), @p7='?', @p8='?', @p9='?' (DbType = DateTime), @p10='?' (Size = 30)], CommandType='Text', CommandTimeout='30']' D6 w/ W/ [) i2 U# h
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")% I" K4 u5 v' H1 U0 w4 {: a
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);' M. p, ?& j) g5 [. f( l, [# W
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline' B2 L+ M. L& }" f* Q0 l# f# P
</code></pre>
9 Q4 P& E% u" `<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
7 s( `( d V- l( b$ K<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>( P& ~0 N0 y3 h& h" x" ~+ w
<h2 id="总结">总结</h2>
& \9 h5 q0 e+ P7 h8 s<p>在本文中我们实现了简单的新增Post操作,这里还有一些涉及到错误处理的内容,我没有在文章中演示,可以参考官方文档 <a href="https://chillicream.com/docs/hotchocolate/defining-a-schema/mutations/#errors">Errors</a>,在自定义异常对象后,有三种方式可以进行错误处理:直接返回异常;使用异常工厂方法;使用构造函数。甚至可以在<code>AggregateExceptions</code>中一次性返回多个异常。基本思路都是通过添加属性<code>[Error(typeof(SomeUserDefinedException))]</code>来实现的。</p>+ |0 q! I# ?4 [) n! f2 \
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>6 `8 z0 M" t, u, k4 d
9 l6 z6 C4 s" _% q) N; z
|
|