|
|
& H- L, N4 Z+ b3 @
<h2 id="系列导航">系列导航</h2>
6 l2 o( O' W" c) a5 V0 F<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>+ s# r8 i7 p5 S( q. B
<h2 id="需求">需求</h2>
- n$ z3 h( ?5 F4 N& e<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>
" J2 }6 _) r; m2 W<h2 id="思路">思路</h2>, }! n6 ]. F! G m9 L, d
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
2 K1 S& W/ [: L; G4 ]# X/ G<h2 id="实现">实现</h2>
$ s% }$ P3 ^& R4 }) a<p>为了保持简单,我们先定义以下两个类型:</p>6 \1 x9 D4 q+ x+ B7 X9 U- J* ]8 a" x
<pre><code class="language-c#">// 定义新增Post的参数
6 O7 C/ k, ~/ x9 bpublic record AddPostInput(string Title, string Author);. e6 U, m1 T; Q1 U. ?) y+ a4 |8 c
$ d) T; K; X, k' H7 u$ p
// 定义新增Post的返回对象
: u( U K0 }4 ^" a. Jpublic record AddPostPayload(Post Post);4 L6 o0 ?( d3 w: b8 v; u4 c7 W" {+ ~- k
</code></pre>/ o9 Z* H1 F3 Y" m0 ?+ f0 {
<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>6 B6 S" A/ D a% U) i0 B' A
<ul>
, i* j7 O3 |* H6 A8 k<li><code>Mutation.cs</code></li>" _* c0 ~3 i7 n, Q4 M
</ul>. t$ g! u$ H* c V+ M- y) q2 I' o
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
" H1 ^: i& i8 ?! y- Z6 a0 v: L* v( [3 I8 ]" s+ D- ]9 ]8 I
public class Mutation2 E/ f! ]. [' O8 Q- n# g
{
4 D- Q; B& F8 d5 E7 S! v' s _; N public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)
3 ^" {' s& j" W; p; B- b {
1 q- Z. P( P O o% V3 {7 C return new AddPostPayload(await repository.AddAsync(new Post
& i9 L4 g; i p, e {
! P$ l, Q2 y- b* h" J, Q* q Title = input.Title,5 j, q) f/ J3 G/ a
Author = input.Author
7 K/ Z2 N) d; k. G; y }));( Z8 n% X3 u0 ~' ^
}
4 Y4 u" w" q" d9 z$ s1 U}6 B! c% B+ z% R/ s6 r K9 Y
* U8 S8 u) k a+ y, T% ?</code></pre>6 f/ O7 w- W3 \7 X, l
<p>最后在注入服务的地方进行配置:</p>
4 v2 A' p( a/ J" p, v( r6 D<ul>
/ Q/ }& h( m. ?- |! b: x<li><code>ProgramExtensions.cs</code></li>* h& X; m9 d& L. A3 U6 Z
</ul>
( R ?5 R+ w$ U& X) Z<pre><code class="language-c#">builder.Services
5 J3 }2 w: A- z) |9 f3 a/ i .AddGraphQLServer()
) x( H5 u2 C2 }) a/ j; K .SetPagingOptions(new PagingOptions
, |+ M( o( t9 C( Q+ k. u {
' A: I' \9 c) u! S, _ _% o( ~ MaxPageSize = 50,* m( P D% x! n o; P9 v& y. i
IncludeTotalCount = true
, @/ F |- R9 t9 A9 Z) B, | })) Y: Z' [ h4 \/ z5 a1 K
.AddFiltering()
0 J4 v! r. j+ U6 c, s .AddProjections()+ X1 [6 o' _' I
.AddSorting()& q* N5 h* ~* s. w
.AddQueryType<Query>()% A) v, [/ N$ J& C! S% R8 K% g# K! I- q' |
.AddMutationType<Mutation>()* ~9 v! ^; I) v- `9 {( F R6 Z: A
.AddMutationConventions(new MutationConventionOptions
0 X& Z7 @8 C/ M1 g' X0 O {0 F- z7 y l, O s/ a
ApplyToAllMutations = true,' u. K& U) z4 F! t, z% p7 J* d
InputArgumentName = "input",& C3 A- a7 F6 d* ]
InputTypeNamePattern = "{MutationName}Input",# t0 ^# V& Y9 Y8 m X, f( V7 U
PayloadTypeNamePattern = "{MutationName}Payload",2 [$ g5 ^9 m7 E3 U5 g1 U
PayloadErrorTypeNamePattern = "{MutationName}Error",
2 |2 K3 c0 E: M h$ `* f, r PayloadErrorsFieldName = "errors"
2 a/ }7 B4 U' o1 F })- b7 @% u* D7 X' u. h3 f
.AddType<PostType>();/ B+ _: e8 r7 T8 r9 Z. E' W
</code></pre>
8 N1 n- @2 N' l<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>8 V( d- Z8 l/ m
<h2 id="验证">验证</h2>
- D2 s! F) l+ c<p>启动<code>Api</code>项目,调用接口:</p>
3 \5 j/ t4 k4 p; n<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>3 C8 [' d5 o( v( ~; M, j
<p>终端的日志输出如下:</p>
$ J a" n7 ]5 u3 ^3 B8 T8 k<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']$ d1 I% Y8 f) k! }6 s9 D
INSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")& |* [' [, m9 {& Q: f3 F8 C
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
: C0 C( `* f# |[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'' m+ E5 Z7 b& s. e; t+ O7 E
</code></pre>3 k& d7 Y' m" ?3 Q. g1 \
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
* a* o! i& b9 a2 d<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
% I1 L4 i. R% @" d( @! g<h2 id="总结">总结</h2>* u: U( x+ a3 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>0 ~- n/ W% {+ K) a
<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p> I8 X* w9 e! b& S3 P
% g/ A1 z3 u- g9 s
|
|