Node.js GraphQL对接Azure SQL返回空字段问题求助
问题:GraphQL API从Azure SQL获取数据后返回字段为空
我正在开发一个GraphQL API,从Azure SQL读取数据并仅返回请求的属性。目前已确认SQL能成功读取到正确记录,但响应中的所有字段均为空,怀疑问题出在SQL返回的Promise处理环节,求修复帮助。
相关代码
var express = require('express'); var app = express(); var fs = require("fs"); const expressGraphQL = require('express-graphql').graphqlHTTP //app.use(express.json()); var TYPES = require('tedious').TYPES; const sql = require('mssql'); const dotenv = require("dotenv") dotenv.config() var { buildSchema } = require('graphql'); var schema = buildSchema(` type Query { course(id: Int!): Course courses(topic: String): [Course] }, type Course { id: Int title: String author: String description: String topic: String url: String } `); var config = { server: "xxxxxxxx.database.windows.net", user: process.env.SQLUSERNAME, password: process.env.SQLPSWRD, database: "xxxxxx", options: { trustedconnection: true, enableArithAbort : true } }; async function readsql(id) { console.log('Reading SQL with id :' + id); try { let pool = await sql.connect(config); let products = await pool.request().query("select * FROM [TestSchema].[Courses] WHERE [id] =" + id); //console.log(products.recordsets); return products.recordsets; } catch (error) { console.log(error); } } var getCourse = function(args) { var id = args.id; console.log("Getting a course " + args); return new Promise(function(resolve, reject){ readsql(id).then(result => { console.log("Inside : "); console.log(result[0]); return resolve(result[0].filter(course => { //return promiseData(result[0]).filter(course => { console.log(course.id); console.log(id); return course.id == id; })); }) }) } let promiseData = () => { return new Promise((resolve, reject) => { getCourse((course) => { resolve(course); }); }); }; // The root provides a resolver function for each API endpoint var root = { course: getCourse, }; app.use('/graphql', expressGraphQL({ schema: schema, rootValue: root, graphiql: true })); var server = app.listen(8081, function () { var host = server.address().address var port = server.address().port console.log("Example app listening at http://%s:%s", host, port) })
GraphQL查询语句
query getSingleCourse($courseID: Int!) { course(id: $courseID) { title author description topic url } }
查询变量
{ "courseID":1 }
响应结果
{ "data": { "course": { "title": null, "author": null, "description": null, "topic": null, "url": null } } }
修复方案
问题集中在Promise处理逻辑、数据格式匹配和SQL安全性三个方面,修复如下:
1. 修正readsql函数(解决数据格式+SQL注入问题)
SQL查询已通过WHERE id=xxx过滤出单条记录,无需后续再做filter;同时改用参数化查询避免注入风险,直接返回单条记录对象:
async function readsql(id) { console.log('Reading SQL with id :' + id); try { let pool = await sql.connect(config); // 参数化查询,避免SQL注入 let products = await pool.request() .input('id', TYPES.Int, id) .query("select * FROM [TestSchema].[Courses] WHERE [id] = @id"); // 返回第一条匹配的记录(ID唯一) return products.recordsets[0][0]; } catch (error) { console.log(error); throw error; // 抛出错误让GraphQL统一处理 } }
2. 简化getCourse函数(消除冗余Promise嵌套)
利用readsql本身的async特性,直接返回Promise结果,避免手动包装Promise:
var getCourse = async function(args) { var id = args.id; console.log("Getting a course with id: " + id); return await readsql(id); }
3. 移除无用代码
删除未被使用的promiseData函数,精简代码结构。
修改后,GraphQL会收到与Course类型完全匹配的对象,即可正确返回对应字段值。
内容的提问来源于stack exchange,提问作者Anupam Chand
相关产品推荐
相关产品推荐

