|
|
4 {( f9 r7 F+ W) { A. f- q1 f; v }4 i
<h2 id="系列导航">系列导航</h2>7 }) }9 t$ e) }
<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>
+ G: F5 x2 _4 B3 T<h2 id="需求">需求</h2># M* h" m/ t* J! G
<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
/ `7 V/ `, O: b6 k5 _6 f<h2 id="思路">思路</h2>
, D' K# \2 U G$ [; Y<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>' j; Q: c* [/ ^6 C; T
<h2 id="实现">实现</h2>/ Y$ ~; u5 N' T' q8 {
<p>为了保持简单,我们先定义以下两个类型:</p>& ]7 t. N( O L/ V7 `& B0 t
<pre><code class="language-c#">// 定义新增Post的参数
' Q* O3 Q5 n3 U& V5 k- @public record AddPostInput(string Title, string Author);+ \2 r, i4 s5 ^
; v4 G$ k I l
// 定义新增Post的返回对象
/ ]" n6 P0 s ?! s# W* [8 W; b6 w! Xpublic record AddPostPayload(Post Post);
( A. m& a5 w c# T$ `9 s+ R</code></pre>
9 n8 q5 t6 G7 P8 h! A' ^* K<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
% W) Z3 F2 \4 ^7 h0 Q7 D7 v- Y: v<ul>" a6 w5 _. H; |- @( W% R6 N
<li><code>Mutation.cs</code></li>
1 x5 a/ o/ v/ V; Q' _</ul>4 T! ]1 D+ u5 q. ~0 C
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
! ~" J% Z! Y7 z ~7 D9 _. ]' r4 z& _, Y
public class Mutation
3 i# P* \" \: J# \6 g2 ]$ R{
2 U9 k) ~. y) ]. h public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
* c( A7 Y3 D2 t. ~* s/ J9 B {
0 T& R9 C2 z1 ` E( I. V8 M7 { return new AddPostPayload(await repository.AddAsync(new Post
6 E( {' [- E8 F5 r* s' c8 E {, {$ F. g- y7 J7 [ _' a' [& Y
Title = input.Title,
3 s& g- C) Z. G; v# @, T Author = input.Author
9 p9 t# M: T0 I# R8 r }));
$ J# m' L0 D5 i1 I8 J/ Y7 | }
: L! e( J/ y' n; s}3 L/ d$ o# c+ R B* Y0 M8 s. S5 H* P/ a
. @8 w; b, p* S( \3 b9 c
</code></pre>
3 G9 Z; a4 m" f6 H# E) }( F<p>最后在注入服务的地方进行配置:</p>: B0 C3 i9 I% f ]( c3 f1 e: j0 a
<ul>
) k. u/ r7 h" z1 G% g: _ p<li><code>ProgramExtensions.cs</code></li>: q8 k. P% @1 s3 g7 `
</ul>" G6 E2 q" w, a0 G* B! z! L% E! |
<pre><code class="language-c#">builder.Services6 V' F p( r) j0 _7 n
.AddGraphQLServer()& l$ N( F3 p8 G2 ?6 E/ h4 j
.SetPagingOptions(new PagingOptions- P9 R) g1 B) |3 S- [
{
. V8 S2 a O% R7 m) o' _ MaxPageSize = 50,9 b3 R: \" C: S+ u" ?
IncludeTotalCount = true4 Q! J( V X4 L: r
})
7 C# _) \( Q, m8 \5 h- a .AddFiltering()! m* w6 I2 ~9 M) F* z: b6 Q" ^
.AddProjections()
* W. P, f6 `# m" b+ E( E" | .AddSorting()
' U5 z9 `* @; e/ T .AddQueryType<Query>()1 A4 T2 Q5 g, u: D( d. r O6 u) u
.AddMutationType<Mutation>()
# j+ ?1 T2 t' m% E3 d3 b u& ^- c* u .AddMutationConventions(new MutationConventionOptions6 a' Q# E' z, G) s
{
W1 A( o# _5 y5 I( ~9 T ApplyToAllMutations = true,
8 p4 X h! |' l5 e9 g' w4 y InputArgumentName = "input",0 P& _# D0 ?( d+ c
InputTypeNamePattern = "{MutationName}Input",
( M0 P2 e U3 M5 j3 p g# C PayloadTypeNamePattern = "{MutationName}Payload",# a5 H8 S& A; T' I7 l; ?( a
PayloadErrorTypeNamePattern = "{MutationName}Error",7 I. x/ p. f+ }5 A3 X( e2 w, l7 @
PayloadErrorsFieldName = "errors"5 l+ K" g8 z2 n" q
})$ g" {4 H3 S! {" D
.AddType<PostType>();. r7 c/ E3 Y6 c
</code></pre>
2 u) W U5 i# W3 {<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
, u9 z9 j! U+ Z) `<h2 id="验证">验证</h2>5 B v/ P& I6 Y5 Q
<p>启动<code>Api</code>项目,调用接口:</p>/ m2 @2 |6 K) K2 i7 P
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>/ i# G9 h2 k. Y8 N6 o
<p>终端的日志输出如下:</p>
* a* C8 h* @! K; m. Q) T<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']
& O& s; y4 b) c0 y2 K' e* g/ R9 z+ }INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")
" w' z: ]- V8 R/ z3 j/ b( E) [% yVALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);, p" G" h4 ]8 Y. }7 H
[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
+ D3 w2 P5 Q( n! @* R* a</code></pre>
) E/ B% b' C+ ]7 ^* o/ y) d, ~<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>' D3 s; Q0 U. g8 p- a; w
<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
4 y0 d5 x$ |' ^8 i<h2 id="总结">总结</h2>
% G% R* r( d- s4 U. j# h7 c<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>( g% v: K( ^9 u h! \) S' D' E
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>/ R4 i: m) ^2 c4 D9 B! x4 b5 m# z
9 c% {. g& E$ Y
|
|