2017-08-01 65 views
0

如何根据搜索结果正确搜索数据库中的某一行以及INSERT/UPDATEINSERT如果未找到,则找到UPDATE,如果找到)?插入或更新获取“交易查询已完成”

目前,我正在做这个:

bookshelf.transaction(async function (t) { 
      for (var x = 0; x < 10; x++) { 
       let row = pmsParser.getRow(x); 
       if (_.isEmpty(row)) { 
        break; 
       } 

       let data = { 
        lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(), 
        mvs: row.version, 
        color: row.color, 
        location: row.location, 
        status: row.status 
       }; 

       new Vehicle({ chassi: row.chassi }) 
        .fetch({ require: true }) 
        .then(model => { 

         return new Vehicle(model) 
          .save(data, { transacting: t, patch: true }); 

        }) 
        .catch(Vehicle.NotFoundError, err => { 
         new Vehicle(data) 
          .save('chassi', row.chassi, { transacting: t }) 
          .then(() => { 
           console.log(`Inserted... ${row.chassi}`); 
          }); 
        }) 
        .catch(err => { 
         console.log(err.message); 
        }); 
      } 
     }) 
      .catch(function (err) { 
       console.error(err); 
       return res.json({ status: false, count: 0, error: err.message }); 
      }); 

我收到此错误:

Transaction query already complete, run with DEBUG=knex:tx for more info 
Unhandled rejection Error: Transaction query already complete, run with DEBUG=knex:tx for more info 
    at completedError (/home/node/app/node_modules/knex/lib/transaction.js:297:9) 
    at /home/node/app/node_modules/knex/lib/transaction.js:266:22 
    at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23) 
    at Function.Promise.attempt.Promise.try (/home/node/app/node_modules/bluebird/js/release/method.js:39:29) 
    at Client_SQLite3.trxClient.query (/home/node/app/node_modules/knex/lib/transaction.js:264:34) 
    at Runner.<anonymous> (/home/node/app/node_modules/knex/lib/runner.js:138:36) 
    at Runner.tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23) 
    at Runner.query (/home/node/app/node_modules/bluebird/js/release/method.js:15:34) 
    at /home/node/app/node_modules/knex/lib/runner.js:61:21 
    at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23) 
    at /home/node/app/node_modules/bluebird/js/release/using.js:185:26 
    at tryCatcher (/home/node/app/node_modules/bluebird/js/release/util.js:16:23) 
    at Promise._settlePromiseFromHandler (/home/node/app/node_modules/bluebird/js/release/promise.js:512:31) 
    at Promise._settlePromise (/home/node/app/node_modules/bluebird/js/release/promise.js:569:18) 
    at Promise._settlePromise0 (/home/node/app/node_modules/bluebird/js/release/promise.js:614:10) 
    at Promise._settlePromises (/home/node/app/node_modules/bluebird/js/release/promise.js:693:18) 

Knex调试输出

knex:tx trx1: Starting top level transaction +0ms 
    knex:tx trx1: releasing connection +28ms 
    knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +15ms 
Transaction query already complete, run with DEBUG=knex:tx for more info 
    knex:tx undefined: Transaction completed: update "vehicles" set "color" = ?, "lastUpdate" = ?, "location" = ?, "mvs" = ?, "status" = ? where "id" = ? +8ms 
Transaction query already complete, run with DEBUG=knex:tx for more info 
+0

你试过设置环境变量声明:'出口DEBUG = knex:tx'? – flaviodesousa

回答

1

当一个事务ALL相关的数据库下访问必须在交易的范围内。

//... 
new Vehicle({ chassi: row.chassi }) 
    .fetch({ require: true, transacting: t }) 
    .then(model => { 
//... 

您的迭代没有正确promisified。这会使您的更改转义事务上下文,导致“事务查询已完成”错误。在循环中创建承诺时,始终建议收集承诺并提交承诺收集处理,例如Promise.all()。这将避免在解决所有承诺之前逃避事务上下文。

这些变化可能会导致如下代码(未经测试):

bookshelf.transaction(async function (t) { 
    let promises = []; 
    for (var x = 0; x < 10; x++) { 
    let row = pmsParser.getRow(x); 
    if (_.isEmpty(row)) { 
     break; 
    } 
    let data = { 
     lastUpdate: moment(row.lastUpdate, 'DD/MM/YYYY - HH:mm').toDate(), 
     mvs: row.version, 
     color: row.color, 
     location: row.location, 
     status: row.status 
    }; 
    promises.push(
     new Vehicle({ chassi: row.chassi }) 
     .fetch({ require: true, transacting: t }) 
     .then(model => { 
      return model // no need to use 'new Vehicle()' here 
      .save(data, { transacting: t, patch: true }); 
     }) 
     .catch(Vehicle.NotFoundError, err => { 
      return new Vehicle(data) // missing 'return' 
      .save('chassi', row.chassi, { transacting: t }) 
      .then(() => { 
       console.log(`Inserted... ${row.chassi}`); 
      }); 
     }) 
     .catch(err => { 
      console.log(err.message); 
      // throw err; // should rethrow it! 
     }) 
    ); 
    } 
    return Promise.all(promises) 
    .catch(function (err) { 
     console.error(err); 
     return res.json({ status: false, count: 0, error: err.message }); 
    }); 
}; 
+0

循环是导入一个具有20K行的CSV文件。如果我向集合中添加20K承诺并同时运行所有这些承诺,会不会有问题? –

+0

当我在开发环境中使用SQLite时,即使我删除了事务,在正确插入/更新了几百行之后,它也会获取'Knex:Timeout获取连接。游泳池可能已经满了。 –

+0

'Promise.all()'只确保所有的承诺都已解决。事实上,当你用20K的更新调用'Promise.all()'时,很可能大部分已经解决了。而且,如果您的交易通常包含20K更新,则可能需要调整数据库。 – flaviodesousa