|
|
/ Y2 D; G. `% c, r/ w+ G0 _$ Z<h2 id="系列导航">系列导航</h2>
# u! x/ I$ s. j3 O( |) P O<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>5 h( y( ^0 I; |
<h2 id="需求">需求</h2>
2 z/ U- R- k0 R( v }$ |<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>1 y3 X. B' a# [
<h2 id="思路">思路</h2>
( p3 M H) f# {, M3 H |<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>; C9 E. i) {. z6 T
<h2 id="实现">实现</h2>
3 M- \6 d [' r* w1 C<p>为了保持简单,我们先定义以下两个类型:</p>
. O! z! D b7 K. _+ O1 z1 O( c<pre><code class="language-c#">// 定义新增Post的参数9 |+ @$ T4 y3 K* ]2 l5 i) z8 k" |
public record AddPostInput(string Title, string Author);
, m0 Z% n% P, |- i7 S7 D" @8 ?, P, j* N5 }" `
// 定义新增Post的返回对象
8 E! c/ E7 n! @3 j, E% Gpublic record AddPostPayload(Post Post);
0 }# O$ }5 c. d</code></pre>: }, v0 ` s9 k- \" F* d7 u
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>4 _8 i7 x. ?1 O: R* b4 }
<ul>
( [) k' ^ [% C) ?6 W" W; W* [( {7 R; W/ M<li><code>Mutation.cs</code></li>
$ ]- B, a9 t0 C0 A! c5 {, J& ?</ul>
% g, A2 h9 b+ E7 g$ m( ]8 M<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
* r9 ?: F a; [1 Q! L5 K3 _& q( `
public class Mutation
4 U! Q! I$ i i5 G{0 W4 j1 ?0 ]6 n$ @' ~
public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
- m: D8 x! Y9 L+ n: a1 M {" M% r7 {; R1 I3 l
return new AddPostPayload(await repository.AddAsync(new Post: n+ p" H" R, Z5 S0 S
{
( w3 F3 ^! h; d, G- y Title = input.Title,+ t! R0 Y( g3 ~3 w: i! n y: p
Author = input.Author
P8 p9 }: c0 N; A0 ?4 z6 Z$ y }));- M* x* U. B: H. K
}! P$ D8 {' Q1 s8 h; e1 D
}/ o1 H7 J) q3 j' |9 q7 K! v2 M
( f/ E! U8 S: q6 R& C</code></pre>
3 n5 k* W5 [6 G- D. o<p>最后在注入服务的地方进行配置:</p>
- e: M1 P+ y0 g5 a<ul>
1 r- ^$ V* N" v& B8 ~<li><code>ProgramExtensions.cs</code></li>
1 _- o3 }4 m2 x R4 |</ul># g* ]1 P6 v! c
<pre><code class="language-c#">builder.Services3 `2 b y; k/ ~
.AddGraphQLServer()
* A8 C! W5 V E! I& @ .SetPagingOptions(new PagingOptions
4 D8 j4 t) p" p/ G5 E- T {% F3 g3 T @& o$ A& v: E
MaxPageSize = 50,
. U) g5 s5 K' o/ P( m IncludeTotalCount = true8 d( |' ^2 O1 A T: s& B$ Y9 Y
})
( t5 W7 O9 W w3 o9 v( B .AddFiltering()
2 z! d' O; ?7 ~6 f2 d8 t .AddProjections()' K9 _: \/ N# w
.AddSorting()
9 e, f; ^ k& F" a8 A .AddQueryType<Query>()
2 K. S& L4 T8 Q3 {& ?, B .AddMutationType<Mutation>()
2 w% v/ a+ ~( @+ J .AddMutationConventions(new MutationConventionOptions/ R7 e$ Q& C Y" j# T2 F
{* w/ q/ U8 C! d% f
ApplyToAllMutations = true,' L% _3 Q5 d" p# V5 T
InputArgumentName = "input",
7 @# I( l, T" ~) ^9 q1 T2 l6 Y/ f InputTypeNamePattern = "{MutationName}Input",, o5 m, W7 S) y2 w
PayloadTypeNamePattern = "{MutationName}Payload",
! E9 {9 U& E3 F( r PayloadErrorTypeNamePattern = "{MutationName}Error",) D: D( `8 N: {2 D: b) F( T
PayloadErrorsFieldName = "errors"
0 i5 ]2 [! E. y })0 q% _2 k# {4 q+ Q! l, ] P6 I
.AddType<PostType>();
% w2 P, I: I; S</code></pre>" u. E2 p+ e0 I. [: [
<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
$ ?) N) {9 e$ ~) {) |9 Z5 K<h2 id="验证">验证</h2>
. B- u- q/ }& \$ f) d* @<p>启动<code>Api</code>项目,调用接口:</p>. i+ [. w, R! k+ N1 C+ B
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>
( y1 I; d& k2 R# w' b<p>终端的日志输出如下:</p>
% ~% B) ^% P! \, X<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']# n* a- m; Y3 M9 J
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title"); \6 M$ c9 i( |
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);6 f" N( \) \7 O l
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
* T& i( p" K4 S7 q8 j</code></pre>$ t' Z! |5 N3 J( I0 o
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p># p3 |/ F4 j' O& `8 v$ Y" z' V5 G
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
3 h v+ p2 Z' y- F) o% f5 N2 [7 e<h2 id="总结">总结</h2>
0 O. b& d" a6 j# E. S& c7 [) @ ]<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>) X9 |# X. ^) o F7 W5 t5 Y0 W
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>, W- v/ Y% z# O' L
! l, s- f( T& Y
|
|