在Microsoft Bot Framework中从SQL数据库中提取数据的异步请求出现问题

时间:2018-02-01 16:12:28

标签: node.js asynchronous azure-sql-database botframework

我在Microsoft bot Framework中有一个机器人,我希望能够从azure SQL数据库中提取数据,以便回答向机器人提出的问题。我已经设置了数据库,里面有一些excel文件。

这是我现在的代码:

var Connection = require('tedious').Connection;
var Request = require('tedious').Request;

var connection = new Connection(dataconfig);  
connection.on('connect', function(err) {  
    console.log("Connected");  
    executeStatement();
});  

var Request = require('tedious').Request;  
var TYPES = require('tedious').TYPES;  

function executeStatement() {  
    request = new Request("select \"Product Name\" from SPA_Data_Feeds where \"Strategic Priority\" = 'Accelerate to Value (LD)'", 
        function(err, rowCount, rows) 
        {
            console.log(rowCount + ' row(s) returned');
        }
    );


    var result = "";
    var count = 0



    request.on('row', function(columns) {
        columns.forEach(function(column) {
            console.log("%s\t", column.value);
            result+= column.value + "\t\n";
            count++;
            if ( count == rowCount ) {
                ATVData(result);
            } ;
        }); 
    });

    connection.execSql(request);
} 

function ATVData(result) { //Puts "result" inside of an adaptive card }

我似乎无法弄清楚如何使if语句正确。 rowCount不起作用,因为它不会等到它首先被函数定义,并且我尝试使用诸如column(s)。length,result(s).length之类的东西但是没有工作。

我还能用其他东西来完成if语句吗?或者我是否需要以回调/承诺的方式重新格式化以使其等待定义rowCount?如果可以,我可以就此提出一些建议吗?

2 个答案:

答案 0 :(得分:1)

  

我还能用其他东西来完成if语句吗?或者我是否需要以回调/承诺的方式重新格式化以使其等待定义rowCount?如果可以,我可以就此提出一些建议吗?

我们可以使用Q.js作为JavaScript Promise实现之一来解决此问题。例如:

var Connection = require('tedious').Connection;
var Request = require('tedious').Request;

var q = require('q');

// Create connection to database
var config = 
   {
     userName: '', // update me
     password: '', // update me
     server: '', // update me
     options: 
        {
           database: '' //update me
           , encrypt: true
        }
   }
var connection = new Connection(config);

// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err) 
   {
     if (err) 
       {
          console.log(err)
       }
    else
       {
           queryDatabase().then(function(result){
            ATVData(result);  
           }, function(err){
              console.log(err);
           });
       }
   }
 );

function queryDatabase()
{ 
    console.log('Reading rows from the Table...');
     //create a promise
     var deferred = q.defer();
    // Read all rows from table
    var result = [];
    var request = new Request(
          "SELECT * From ForumMessages",
             function(err, rowCount) 
                {
                    deferred.resolve(result);
                });

     request.on('row', function(columns) {
        columns.forEach(function(column) {
            console.log("%s\t%s", column.metadata.colName, column.value);
            result.push(columns);
         });
     });
     connection.execSql(request);
     //return the promise
     return deferred.promise;
}

function ATVData(result){
    //your bot code goes here
}

答案 1 :(得分:0)

我想扩展Grace的答案,对于每一行,你也可以为一些实用程序做这个:

 request.on('row', function(columns) {
    var singleResult = {};
    columns.forEach(function(column) {
        console.log("%s\t%s", column.metadata.colName, column.value);

        // Add a property to the singleResult object.
        singleResult[column.metadata.colName] = column.value;

        // Push the singleResult object to the array.
        result.push(singleResult);
     });
 });

然后,您可以在机器人的代码中使用点表示法通过属性名称调用每个对象,例如:result[x].colName其中colName是列的名称(在这种情况下是对象属性)。

示例(假设数据库中至少有一个结果项,带有数据的“链接”列):

var adaptiveCardExample = {
    'contentType': 'application/vnd.microsoft.card.adaptive',
    'content': {
        '$schema': 'http://adaptivecards.io/schemas/adaptive-card.json',
        'type': 'AdaptiveCard',
        'version': '1.0',
        'body': [ 
            {
                "type": "TextBlock", 
                "text": "Code Example"
            },
            {
                "type": "TextBlock", 
                "text": "We're going to " + result[0].link,
                "wrap": true
            }],
            'actions': [
                {
                    'type': 'Action.OpenUrl',
                    'title': 'Go to the example link',
                    'url': result[0].link
                }
            ]
        }
    };

var adaptiveCardMsg = new builder.Message(session).addAttachment(adaptiveCardExample);
session.send(adaptiveCardMsg);

作为预防措施,如果属性是数据库中的可空字段,您可能需要为该属性添加null或undefined检查。