|
|
$ S. @" D# i3 Z# [6 |<h2 id="系列导航">系列导航</h2>
, w$ U+ ?' X; h F% l7 J' e1 D6 p2 W<p><a href="https://www.cnblogs.com/code4nothing/p/graphql-net6-0.html">使用Hot Chocolate和.NET 6构建GraphQL应用文章索引</a></p>, O, R! V3 v) @0 ~" ?4 t
<h2 id="需求">需求</h2>
& a0 E! P8 Q6 }" W; H5 T2 F<p>在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务。</p>/ B5 m) c8 d2 [: h) X& Q' \
<h2 id="思路">思路</h2>2 T- z, u: b8 B7 X) Z2 J- w
<p>在GraphQL中,对数据进行查询使用<code>query</code>,而对于修改数据则需要使用<code>mutation</code>,包括新增和修改数据。Hot Chocolate在使用Mutation的逻辑上和使用Query的基本一致,但是需要根据需要定义用于创建或者更新的数据对象,所以我们直接进行实现。</p>
( K- o. N6 N& b9 z& B. q<h2 id="实现">实现</h2>; I4 F1 ^& s# y* ~, U+ ~1 l
<p>为了保持简单,我们先定义以下两个类型:</p>( i% M" G4 h) N- }
<pre><code class="language-c#">// 定义新增Post的参数
6 a' Q* y' {9 t) X- Zpublic record AddPostInput(string Title, string Author);. n3 V9 J! F' J$ _# B# |
6 E/ M; a& Y4 k9 O2 Y( D" u& z
// 定义新增Post的返回对象
) a( f3 k4 H6 _0 m( T" Tpublic record AddPostPayload(Post Post);1 z/ q) S o" T' j
</code></pre>
9 W: l2 [; |0 h& N5 G4 Z' S<p>新建<code>Mutation.cs</code>用来定义相关接口:</p>
' u2 B; H: H) x K<ul>
" e( Z* S8 M* p5 p7 `) d7 t<li><code>Mutation.cs</code></li>% D4 D% `$ z7 d
</ul>/ l4 \3 T( P7 ~! L. k( ~
<pre><code class="language-c#">namespace PostGraphi.Api.GraphQL;
. Y" {# [9 C8 B0 { K0 a! t5 ~( \3 x* r
public class Mutation# X$ u4 K- Z, s, j* M9 W% R6 E B& ~
{
2 U( K+ v1 T# @( l+ F public async Task<AddPostPayload> AddPostAsync(AddPostInput input, [Service] IRepository<Post> repository)9 t$ ]) L# X% j. n; J
{
6 p; j0 n5 ^1 O8 J' q P return new AddPostPayload(await repository.AddAsync(new Post
) [" P K# X |5 n+ | {" G+ ]. f, |# }8 E7 {' `. _5 S' n; O
Title = input.Title,
) y- n8 H9 H3 e# G8 E" ? Author = input.Author
& N+ Y3 z% E" J n& L; r% B }));3 g* c4 O ?7 p6 F7 Z2 m
}
$ q' [& m; C0 [# @$ Q3 v}
6 O: p) u4 W& r% H% \& }' Z: ~
3 X7 D2 ~0 ^$ C! \; Q</code></pre>
& @4 v! a }( V( E; c<p>最后在注入服务的地方进行配置:</p>' E! [& v% }, h* L
<ul>
2 B4 D8 _4 J2 H<li><code>ProgramExtensions.cs</code></li>
8 n; |/ R9 Y: E( g+ P' J" Y1 ?. N</ul>
- p: v: ~1 i/ w/ M. m/ v<pre><code class="language-c#">builder.Services
; R! M+ i/ z) A+ ` .AddGraphQLServer()
) y: x+ m! C1 _, E2 Y .SetPagingOptions(new PagingOptions
0 ^# |0 t7 p, w' z) Z% _ {( Y5 B' }' `! P5 |: O- {
MaxPageSize = 50,+ \4 S J3 \+ d) N7 S' J
IncludeTotalCount = true( j0 w- }: y. ?# h
})
+ x6 r2 i' X# c; l .AddFiltering()
4 M4 b, V' ^( A! _ .AddProjections()
3 C; w+ |8 c4 N .AddSorting()# x2 K9 I: \; }! P
.AddQueryType<Query>()' e2 }, n# ~" c d* u3 h- x
.AddMutationType<Mutation>()
2 d3 y- K* I) x) R .AddMutationConventions(new MutationConventionOptions1 G" {2 j& \) {; Y8 D# ~" Q; N
{4 O1 C7 c; Z/ D9 Y( j4 k6 }
ApplyToAllMutations = true,! g1 U; s3 h& c/ j: m% S
InputArgumentName = "input",; R9 B; |2 R% x7 B
InputTypeNamePattern = "{MutationName}Input",3 k7 g3 x% E0 G$ O* k
PayloadTypeNamePattern = "{MutationName}Payload",
+ W& n& B# m, @' v ^: h& \$ ~ PayloadErrorTypeNamePattern = "{MutationName}Error",; h+ ?& W" W: N
PayloadErrorsFieldName = "errors"
% E, l6 c( u2 L; \5 n! I$ S })& } `2 d( f0 W( v9 q( u
.AddType<PostType>();
- Y* N4 O, I) g</code></pre>
; Q) o4 Y [) C- F: ]/ h' z+ D+ K1 d<p>这样就实现了新增Post的需求,下面我们来验证一下。</p>
8 `$ k* Q% w4 d) { k* q<h2 id="验证">验证</h2>
% d0 V! Q# [+ I6 N4 y<p>启动<code>Api</code>项目,调用接口:</p>
: ?1 y: s \. M$ L/ O7 D. B<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104544617-1400586374.png" ></p>5 C# e7 S7 y" f& @+ e
<p>终端的日志输出如下:</p>+ m6 y) a2 Q$ q% d) ^
<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']
* E& S ~' u- A9 w6 M; C8 VINSERT INTO "Posts" ("Id", "Abstraction", "Author", "Content", "Created", "CreatedBy", "LastModified", "LastModifiedBy", "Link", "PublishedAt", "Title")( w( E" N/ P/ \9 V8 ? X. S) `$ M5 k
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10);
, p! B7 r2 h' E4 n( f$ g& Q[10:45:15 INF] Executed endpoint 'Hot Chocolate GraphQL Pipeline'
. t' H% e1 v Y4 Q" Z- `</code></pre>2 k; ?% A# h! e' e7 h6 K7 L7 z
<p>可以看到新建的Post已经存储到数据库中了,我们可以通过查询接口来获取详情:</p>
7 _' @7 F7 k; U e6 u<p><img src="https://img2022.cnblogs.com/blog/2487237/202202/2487237-20220211104851825-1533915064.png" ></p>
9 b1 L" r. v5 l \- V" Z<h2 id="总结">总结</h2>
$ r+ R+ b$ X$ T& i& A3 B- N" M0 m<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>
' \( [& D7 _; ?& q% x+ i<p>在下一篇文章中,我们通过<code>Mutation</code>对已有数据进行更新。</p>' F0 |% u8 K Y; B U
/ R K, _6 k% C( t6 j5 P4 U |
|