UWP GraphQL数据查询的实现

1. 缘起

Facebook 的移动应用从 2012 年就开始使用 GraphQL。GraphQL 规范于 2015 年开源,现已经在多种环境下可用,并被各种体量的团队所使用。

这个链接可以看到更多的GraphQL使用者。

2. GraphQL是什么

英文官网:GraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data.

中文官网:GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。

个人理解:GraphQL利用了传统的SQL查询,并且以restful api的形式返回数据。

举个栗子:

传统的Restful api查询,你要查询一个用户的头像信息,不需要别的信息,那么就是需要利用Http发送给服务区user_id,然后服务器返回给你这个用户的所有信息,比如邮箱、昵称、电话、头像等信息。

这样以来,如果返回的数据过大的话,可能会因为网络的各种问题导致延迟。

但是如果像GraphQL,我要查询头像信息,只需要发送

{
  hero {
    head_url
  }
}

那么服务器就只会返回给

{
  "hero": {
    "head_url": "https://pic.cnblogs.com/face/298986/20150104103009.png"
  }
}

嗯,基本就是这样子。仅仅是我的理解,如果不对,麻烦大声告诉我,谢谢。

官网还有一个gif,更加形象。

怎么样,可以的吧。

3. 现存的GraphQL框架

前面说了,GraphQL仅仅就是一个查询语言,如果想用在自己的项目中,你不可能从头开始研究这个语言,然后手撸自己需要的框架。当然,自己写当然没问题。

不过官网提供了一些自己写的或者第三方写的库,包括服务器端和客户端的实现。

详见 ↓

英文:https://graphql.org/code/

中文:https://graphql.cn/code/

这其中不得不赞一下一个第三方的Apollo,牛逼的不要不要的。写了Android、iOS、Javascript,就是不写dot net

.net下不过也有三个:

第一个好像是微软写的,261 stars。。。不过距离上一个版本发版已经有一年了,这一年有了一些新的bug,但是他们之说下一个版本解决,但是需要多久???God knows。

第二个是个人开发者写的,80 stars。但是距离他上一次提交代码是三年前了,so。。。放弃吧先

第三个也是个人开发者写的,26 stars。这个库更新的比较频繁,可以使用。

4. 一个简单的例子

拿微软的例子GraphQL.Client说一下吧

比如就从服务器获取一个pin code

首先自己先写好mutation句子,类似SQL查询的语句。

@"mutation{
                    generatePinCode
                }"

还是有一点点麻烦的地方,就是自己要写查询语句。

像刚才提到的Apollo框架,人家都是给你自动生成的,你气不气。

不过有人在Github提问了,但是微软的人并不打算这么做,可能他们在忙别的事情吧,比如写win10的bug

然后声明一个GraphQL的Client,指定EndPoint地址。

            GraphQLClient client = new GraphQLClient(new GraphQLClientOptions
            {
                EndPoint = new Uri("http://dev.xxx.com/api/graphql/guest")
            });

然后声明GraphQLResponse,来接受服务器返回的消息。

GraphQLResponse response = await client.PostQueryAsync(
                @"mutation{
                    generatePinCode
                }");

            if(response.Errors == null)
            {
                var result = response.GetDataFieldAs<string>("generatePinCode");
                textBox_Result.Text = textBox_PinCode.Text = result;
            }
            else
                textBox_Result.Text = "Generate Pin Code Failed";

看,就是这么简单的例子。

有人可能好奇,上面的generatePinCode是什么鬼?在哪里出来的。

其实这个是服务器返回来的数据,我们需要从generatePinCode数据区拿数据而已。

说到这里,那么就不得不说一下Altair这个神器了。

在Altair中,发送请求,返回来的数据都是包含在data数据体中的。data里面的generatePinCode才是我们真正想要的。

而通过Altair看出,generatePinCode其实返回了就是一个string类型的字符串。

那么我们只需要GetDataFieldAs函数,直接反序列化即可。

5. 一个有一点点复杂的例子

拿微软的例子GraphQL.Client说一下吧

比如需要做个用户输入用户名密码登录的例子:

那么我们写一个简单的xaml代码:

<TextBox x:Name="textBox_Username" PlaceholderText="user name" BorderThickness="1" Margin="0, 20"/>
<TextBox x:Name="textBox_pswd" PlaceholderText="password" BorderThickness="1"/>
<Button Content="Login" Margin="0, 20" Tapped="LoginWithUsernamePassword_Tapped"/>

然后自己需要写mutation代码,这里我们就查询user 的所有信息。不过这些信息可以按需自己获取。

@"mutation{
                    login(email:""" + textBox_Username.Text
                    + @""", password:"""+ textBox_pswd.Text
                    + @"""){
                    access_token
                    token_type
                    expires_in
                    user{id
                        email
                        nickname
                        email_verified_at
                        password
                        remember_token
                        mobile
                        gender
                        birthdate
                        type
                        avatar_uri
                        avatar_radius_uri
                        status
                        auth_privacy
                        account_type
                        created_at
                        updated_at}
                    }
                    }";

然后在C#里面响应 LoginWithUsernamePassword_Tapped 时间。

先声明一个GraphQL的Client,指定EndPoint地址。

GraphQLClient client = new GraphQLClient(new GraphQLClientOptions
            {
                EndPoint = new Uri("http://dev.xxx.com/api/graphql/guest")
            });

然后声明GraphQLResponse,来接受服务器返回的消息。

            GraphQLResponse response = await client.PostQueryAsync(query);
            if (response.Errors == null)
            {

            }
            else
                textBox_Result.Text = "Login With Username Password Failed";

其实看上面的代码,可以看出,和我们之前用Restful Api的方式一模一样。

1. 向指定的url发送请求

2. 获取相应信息

3. 判断返回的消息是否成功,比如status code等。

如果GraphQL返回的Response.Errors是空的话,表示查询成功。接下来要对数据进行反序列化处理,以便接下来我们可以直接使用。

                var result = response.GetDataFieldAs<LoginWithPinCode>("login");
                textBox_Result.Text = result.access_token;
                image_Head.Source = new BitmapImage(new Uri(result.user.avatar_radius_uri));

到这里,可能会有人好奇"login"是怎么来的?

在Altair中,发送请求,返回来的数据都是包含在data数据体中的。data里面的login才是我们真正想要的。

而LoginWithPinCode类是根据返回的login数据,自己定义的model。

好了,到此。一个完整的利用用户名密码登录的例子就完成了。

C#完整代码:

        private async void LoginWithUsernamePassword_Tapped(object sender, TappedRoutedEventArgs e)
        {
            client = new GraphQLClient(new GraphQLClientOptions
            {
                EndPoint = new Uri("http://dev.xxx.com/api/graphql/guest")
            });

            string query = @"mutation{
                    login(email:""" + textBox_Username.Text
                    + @""", password:"""+ textBox_pswd.Text
                    + @"""){
                    access_token
                    token_type
                    expires_in
                    user{id
                        email
                        nickname
                        email_verified_at
                        password
                        remember_token
                        mobile
                        gender
                        birthdate
                        type
                        avatar_uri
                        avatar_radius_uri
                        status
                        auth_privacy
                        account_type
                        created_at
                        updated_at}
                    }
                    }";

            GraphQLResponse response = await client.PostQueryAsync(query);

            if (response.Errors == null)
            {
                var result = response.GetDataFieldAs<LoginWithPinCode>("login");
                textBox_Result.Text = result.access_token;
                image_Head.Source = new BitmapImage(new Uri(result.user.avatar_radius_uri));
            }
            else
                textBox_Result.Text = "Login With Username Password Failed";
        }

6. GraphQL使用总结

如果你的项目突然说要换GraphQL方式查询之类的,不要慌。没听过没关系,它也是一个api,通过结合了SQL查询的方式实现。

上面的两个例子都是用微软的库实现的。

如果这三个库都不能满足你的要求,那么就需要用dot net提供的HttpClient来从最底层做起。这样有个好处就是你可以完全按照自己的需要定制。

像前面提到的Apollo框架,它就存在这样那种的限制。Android和iOS开发组,在几个schema文件上花费了好大一段时间,又是合并文件又是命名空间啥的。

不过由于微软的那个库(其实也就是封装了HttpClient,做多了一点处理),封了虽然并没有那么的理想,反而避开了schema这一点。

如果你从HttpClient,当然更不会存在这种问题了。

原文地址:https://www.cnblogs.com/hupo376787/p/12076841.html

时间: 2024-08-30 03:22:56

UWP GraphQL数据查询的实现的相关文章

MongoDB数据查询

启动MongoDB:sudo service mongodb start,mongo 经测试,键可加引号也可不加,但是值一般要加引号,数值类型除外 MongoDB区分大小写,命名通常采用驼峰式命名法 MongoDB在使用数据库,插入集合等情况下,若数据库/集合不存在将自动创建 数据查询find() db.<集合名>.find({<键名>:<值>,...}) 格式化结果集:后加.pretty()即db.<CollectionName>.find({key:'v

用python操作mysql数据库(之数据查询结果返回字典类型)

#!/usr/bin/env python # -*- coding: utf-8 -*- import MySQLdb #建立连接 conn = MySQLdb.connect(host='127.0.0.1',user='root',passwd='1qaz#EDC',db='test_db') cur = conn.cursor(MySQLdb.cursors.DictCursor) #建立游标时,加上"MySQLdb.cursors.DictCursor",让数据查询结果返回字

SharePoint服务器端对象模型 之 使用CAML进展数据查询

SharePoint服务器端对象模型 之 使用CAML进行数据查询 一.概述 在SharePoint的开发应用中,查询是非常常用的一种手段,根据某些筛选.排序条件,获得某个列表或者某一些列表中相应的列表条目的集合. 除去列表上的查询之外,在SharePoint中还大量存在着各种各样的查询,比如针对回收站的SPRecycleBinQuery.针对审计的SPAuditQuery.针对变更的SPChangeQuery等等,不过这些查询在实际项目中使用到的频率并不是很高.本章节还是着重介绍列表查询功能.

6、SQL Server 数据查询

一.使用SELECT检索数据 数据查询是SQL语言的中心内容,SELECT 语句的作用是让数据库服务器根据客户要求检索出所需要的信息资料,并按照规定的格式进行整理,返回给客户端. SELECT 语句的基本结构 [WITH<common_tale_expression>] SELECT select_list [INTO new_table_name] [FROM table_source][where search_condition] [GROUP BY group_by_expressio

数据库 简单的数据查询

简单的数据查询 1.查询的基本结构: select[distinct] */列名 from table 表名 [where condition] [order by] 2.投影的操作:指定查询结果中能够显示的列 语法:select 列名列表 from 表名; (1):选择多列查询,列名之间用“,”隔开 (2):单列时,只单个. (3):若选择所有列,则用*代替. 3.表名前缀:本列无多大意义,但在复杂的多表查询的情况下,很有用. 语法:select 列名表名 from 表名; 4.列别名(as)

Hibernate数据查询(转)

Hibernate Query Language(HQL)Criteria QueryNative SQL下面对其分别进行解释Hibernate Query Language:HQL提供了是十分强大的功能,它是针对持久化对象,用取得对象,而不进行update,delete和insert等操作.而且HQL是面向对象的,具备继承,多态和关联等特性.from子句:from子句是最简单的HQL,例如from Student,也可以写成 select s from Student s.它简单的返回Stud

我们曾经心碎的数据库之 数据查询基础

第九章  数据查询基础 1.记录集: 记录集是符合查询条件的记录组织在一起的类似于表结构的查询结果 2.使用select语句进行查询 语法: select 列名 from 表名 where 查询条件表达式 order by 排序的列名 [asc或desc] 1.查询所有的数据行和列 select * from students 2.查询部分行和列 select 列名  from 表名 where  查询条件表达式 3.在查询中使用列的别名 select scode as 学生编号,sname a

数据查询和管理

对数据表的插入.更新.删除操作    --数据查询和管理--取消重复元组distinctselect distinct 民族 from 学生信息go--查询前几列数据select top 6 * from 学生信息select top 6 学号,姓名,民族 from 学生信息go--查询计算列select 教师编号 as 'sno',姓名 as 'sname',2015-年龄 as 'sbrisday' from 教师信息go--使用别名查询,在列表中的名称,可使用的方法:空格,as,=,别名用

二级缓存 对数据查询

二级缓存:存放公有数据 1.适用场合: 1.数据不能频繁更新 2.数据能公开,私密性不是很强 2.hibernate本身并没有提供二级缓存的解决方案 3.二级缓存的实现是依赖于第三方供应商完成的 ehcache oscache jbosscache swamchache 4.二级缓存的操作 1.二级缓存存在sessionFactory中 2.生命周期:与sessionFactory保持一致 3.使用二级缓存的步骤 1.在hibernate.cfg.xml <property name="c