繁体   English   中英

如何使用node.js,mssql和msnodesqlv8在事务中正确执行循环查询

[英]How to perform looped queries in transactions properly with node.js, mssql and msnodesqlv8

我试图做我以前在c#和asp.net Webforms中所做的事情,并在事务中执行许多插入存储过程,其中一些是循环的。 我现在正尝试通过具有mssql包的node.js在我的角度应用程序中执行此操作。 到目前为止,我所拥有的如下。

    //Insert Change Record
router.post('/insertChange', (req, res) => {
    const transaction = new sql.Transaction(conn);

    transaction.begin(err => {
        let rolledBack = false;
        transaction.on('rollback', aborted => {
            rolledBack = true;
        })
        const request = new sql.Request(transaction);
        request.input('ChangeTitle', req.body.changeTitle);
        request.input('TypeId', req.body.typeId);
        request.input('DateSubmitted', req.body.dateSubmitted);
        request.input('TargetDate', req.body.targetProductionDate);

        request.input('ChangeSponsor', req.body.changeSponsor);
        request.input('UATDate', req.body.dateReadyUAT);
        request.input('ChangeSponsorEmail', req.body.changeSponsorEmail);
        request.input('ClarityId', req.body.clarityId);
        request.input('ChangeDescription', req.body.changeDescription);

        request.input('ComponentName', req.body.componentName);
        request.input('ComponentDescription', req.body.componentDescription);

        request.input('ReasonForChange', req.body.reasonForChange);
        request.input('ComponentREplacing', req.body.componentReplacing);
        request.input('DependentChange', req.body.dependentChange);

        request.input('InstallOption', req.body.installOption);
        request.input('RebootRequired', req.body.rebootRequired);
        request.input('UserIntervention', req.body.userIntervention);
        request.input('Activation', req.body.activation);

        request.input('ContingencyPlan', req.body.contingencyPlan);
        request.input('AdditionalInformation', req.body.additionalInformation);

        request.input('PerformanceImpact', req.body.applicationPerformance);
        request.input('IsPCoERequired', req.body.pcoeTesting);
        request.input('IsCanadianRetailBranch', req.body.pbsTesting);

        request.input('BusinessAppImpact', req.body.businessApplication);
        request.input('NetworkImpact', req.body.networkPerformance);
        request.input('NewInfrastructure', req.body.newInfrastructure);
        request.input('LogonTime', req.body.logonTime);
        request.input('AdditionalTechnicalInformation', req.body.additionalAssessmentInfo);

        request.input('IsProdIssue', req.body.isProdIssue);
        request.input('ProdIssue', req.body.productionIssue);
        request.input('ProdIncidentNum', req.body.incidentNumbers);
        request.input('IsMajorChange', req.body.isMajorChange);
        request.input('HasRequiredTesting', req.body.hasRequiredTesting);
        request.input('HasPackageSubmit', req.body.hasPackageSubmit);
        request.input('SignOffETA', req.body.signoffETA);
        request.input('SpecificTesting', req.body.specificTesting);
        request.input('SpecificPilot', req.body.specificPilot);
        request.input('PilotInfo', req.body.pilotTransits);

        request.input('UserChanges', req.body.userDifferences);
        request.input('ServiceDeskProcedure', req.body.procedureSupport);
        request.input('SupportCallFlowId', req.body.supportCallFlow);

        request.input('OverallChangeStatus', 1);

        let changeId = request.output('changeId', sql.Int);

        request.execute('dbo.InsertChange').then(function (result) {
            console.dir(result);
        }).catch(function (err) {
            console.dir(err);
        });

        async.each(
            req.body.changeType
            ,function iterator(item, next) {
            const requestCT = new sql.Request(transaction);
            requestCT.input('ChangeId', changeId);
            requestCT.input('TypeOfChangeId', item.typeOfChangeId);
            requestCT.input('Description', item.description);
            requestCT.execute('dbo.InsertTypeOfChange').then(function (result) {
                console.dir(result);
                next();
            }).catch(function (err) {
                console.dir(err);
            });
        })
        async.each(
            req.body.serviceImpacted
            ,function iterator(item, next) {
            const requestSI = new sql.Request(transaction);
            requestSI.input('ChangeId', changeId);
            requestSI.input('ServicesImpactedId', item.serviceImpactedId);
            requestSI.execute('dbo.InsertImpactedService').then(function (result) {
                console.dir(result);
                next();
            }).catch(function (err) {
                console.dir(err);
            });
        })
        async.each(
            req.body.businessImpacted
            ,function iterator(item, next) {
            const requestBI = new sql.Request(transaction);
            requestBI.input('ChangeId', changeId);
            requestBI.input('BusinessImpactedId', item.businessImpactedId);
            requestBI.execute('dbo.InsertImpactedBusiness').then(function (result) {
                console.dir(result);
                next();
            }).catch(function (err) {
                console.dir(err);
            });
        })
        async.each(
            req.body.criticalApp
            ,function iterator(item, next) {
            const requestCA = new sql.Request(transaction);
            requestCA.input('ChangeId', changeId);
            requestCA.input('CriticalBankingId', item.criticalId);
            requestCA.input('Description', item.description);
            requestCA.execute('dbo.InsertCriticalBankingApp').then(function (result) {
                console.dir(result);
                next();
            }).catch(function (err) {
                console.dir(err);
            });
        })
        async.each(
            req.body.testStages
            ,function iterator(item, next) {
            const requestTS = new sql.Request(transaction);
            requestTS.input('ChangeId', changeId);
            requestTS.input('TestStageId', item.testStageId);
            requestTS.input('TestDate', item.testDate);
            requestTS.input('Description', item.description);
            requestTS.execute('dbo.InsertChangeTest').then(function (result) {
                console.dir(result);
                next();
            }).catch(function (err) {
                console.dir(err);
            });
        })

        if (err) {
            if (!rolledBack) {
                transaction.rollback(err => {
                    console.dir(err);
                    // ... error checks
                })
            }
        } else {
            transaction.commit(err => {
                console.dir(err);
                // ... error checks

            })
        }
    })
});

的确,在线上确实没有太多的材料可以用来处理带有存储过程的交易,而对于像这样的大型交易则更少。 但是我收到的错误是在终端日志中多次出现以下错误。

{ TransactionError: Can't acquire connection for the request. There is another request in progress.
at Transaction.acquire (C:\Users\Redirection\meecd26\Documents\GitRepo\td-angular-starter\node_modules\mssql\lib\base.js:740:30)
at Immediate._query.err [as _onImmediate] (C:\Users\Redirection\meecd26\Documents\GitRepo\td-angular-starter\node_modules\mssql\lib\msnodesqlv8.js:417:19)
at runCallback (timers.js:781:20)
at tryOnImmediate (timers.js:743:5)
at processImmediate [as _immediateCallback] (timers.js:714:5) code: 'EREQINPROG', name: 'TransactionError' }

这肯定表明我执行事务不正确。

有人可以帮助指导我如何改进和解决此问题吗?

编辑:更改我的代码以反映我在这里找到的内容,并对我的第一个插入内容进行一些更改。 虽然我的第一个插入确实起作用,但仍然遇到上面的重复错误,所以现在我知道我的问题是如何在循环内部实现插入。 有没有办法可以在每次插入时关闭连接? 那是我应该尝试的方法吗?

我最终使它工作了,尽管我对所有工作原理的理解根本没有改善,但我至少可以发表自己的看法,希望其他人希望对它有所帮助。

router.post('/insertChange', (req, res) => {
console.log("Beginning of POST, before initializing transaction");

let changeId;
let mainInsert = false;

beginTransaction(function (err, rollback, transaction) {
    if (err) {
        // return cb(err);
    }
    let request = new sql.Request(transaction);
    // request.verbose = true;
    request.input('ChangeTitle', req.body.ChangeTitle);
    request.input('TypeId', req.body.TypeId);
    request.input('DateSubmitted', req.body.DateSubmitted);
    request.input('TargetDate', req.body.TargetDate);

    request.input('ChangeSponsor', req.body.ChangeSponsor);
    request.input('UATDate', req.body.UATDate);
    request.input('ChangeSponsorEmail', req.body.ChangeSponsorEmail);
    request.input('ClarityId', req.body.ClarityId);
    request.input('ChangeDescription', req.body.ChangeDescription);

    request.input('ComponentName', req.body.ComponentName);
    request.input('ComponentDescription', req.body.ComponentDescription);

    request.input('ReasonForChange', req.body.ReasonForChange);
    request.input('ComponentReplacing', req.body.ComponentReplacing);
    request.input('DependentChange', req.body.DependentChange);

    request.input('InstallOption', req.body.InstallOption);
    request.input('RebootRequired', req.body.RebootRequired);
    request.input('UserIntervention', req.body.UserIntervention);
    request.input('Activation', req.body.Activation);

    request.input('ContingencyPlan', req.body.ContingencyPlan);
    request.input('AdditionalInformation', req.body.AdditionalInformation);

    request.input('PerformanceImpact', req.body.PerformanceImpact);
    request.input('IsPCoERequired', req.body.IsPCoERequired);
    request.input('IsCanadianRetailBranch', req.body.IsCanadianRetailBranch);

    request.input('BusinessAppImpact', req.body.BusinessAppImpact);
    request.input('NetworkImpact', req.body.NetworkImpact);
    request.input('NewInfrastructure', req.body.NewInfrastructure);
    request.input('LogonTime', req.body.LogonTime);
    request.input('AdditionalTechnicalInformation', req.body.AdditionalTechnicalInformation);

    request.input('IsProdIssue', req.body.IsProdIssue);
    request.input('ProdIssue', req.body.ProdIssue);
    request.input('ProdIncidentNum', req.body.ProdIncidentNum);
    request.input('IsMajorChange', req.body.IsMajorChange);
    request.input('HasRequiredTesting', req.body.HasRequiredTesting);
    request.input('HasPackageSubmit', req.body.HasPackageSubmit);
    request.input('SignOffETA', req.body.SignOffETA);
    request.input('SpecificTesting', req.body.SpecificTesting);
    request.input('SpecificPilot', req.body.SpecificPilot);
    request.input('PilotInfo', req.body.PilotInfo);

    request.input('UserChanges', req.body.UserChanges);
    request.input('ServiceDeskProcedure', req.body.ServiceDeskProcedure);
    request.input('SupportCallFlowId', req.body.SupportCallFlowId);

    request.input('OverallChangeStatus', 1);

    request.output('changeId', sql.Int);

    request.execute('dbo.InsertChange', function (err, callback) {
        if (err) {
            console.dir(err);
            rollback(err);
            res.status(400).send("Failed to submit change form.");

        } else {
            mainInsert = true;
        }

        if (callback) {
            changeId = +callback.returnValue;
        }

        if (mainInsert) {
            async.each(
                req.body.changeType, function iterator(item, next) {
                    request = new sql.Request(transaction);
                    request.input('ChangeId', changeId);
                    request.input('TypeOfChangeId', item.typeOfChangeId);
                    request.input('Description', item.description);
                    request.execute('dbo.InsertTypeOfChange', function (err, callback) {
                        if (err) return next(err);
                        console.dir(callback);
                        next();
                    })
                }, function fin(err) {
                    if (err) {
                        rollback(err);
                        return; //done
                    }
                })
            async.each(
                req.body.serviceImpacted, function iterator(item, next) {
                    request = new sql.Request(transaction);
                    request.input('ChangeId', changeId);
                    request.input('ServicesImpactedId', item.serviceImpactedId);
                    request.execute('dbo.InsertImpactedService', function (err, callback) {
                        if (err) return next(err);
                        console.dir(callback);
                        next();
                    })
                }, function fin(err) {
                    if (err) {
                        rollback(err);
                        return; //done
                    }
                })
            async.each(
                req.body.businessImpacted, function iterator(item, next) {
                    request = new sql.Request(transaction);
                    request.input('ChangeId', changeId);
                    request.input('BusinessImpactedId', item.businessImpactedId);
                    request.execute('dbo.InsertImpactedBusiness', function (err, callback) {
                        if (err) return next(err);
                        console.dir(callback);
                        next();
                    })
                }, function fin(err) {
                    if (err) {
                        rollback(err);
                        return; //done
                    }
                })
            async.each(
                req.body.criticalApp, function iterator(item, next) {
                    request = new sql.Request(transaction);
                    request.input('ChangeId', changeId);
                    request.input('CriticalBankingId', item.criticalId);
                    request.input('Description', item.description);
                    request.execute('dbo.InsertCriticalBankingApp', function (err, callback) {
                        if (err) return next(err);
                        console.dir(callback);
                        next();
                    })
                }, function fin(err) {
                    if (err) {
                        rollback(err);
                        return; //done
                    }
                })
            async.each(
                req.body.testStages, function iterator(item, next) {
                    request = new sql.Request(transaction);
                    request.input('ChangeId', changeId);
                    request.input('TestStageId', item.testStageId);
                    request.input('TestDate', item.testDate);
                    request.input('Description', item.description);
                    request.execute('dbo.InsertChangeTest', function (err, callback) {
                        if (err) return next(err);
                        console.dir(callback);
                        next();
                    })
                }, function fin(err) {
                    if (err) {
                        rollback(err);
                        return; //done
                    }
                    else {
                        transaction.commit(function (err) {
                            if (err) {
                                console.error('Transaction commit error: ', err);
                                res.status(400).send("Failed to submit change form.");
                            } else {
                                console.error('Transaction commit success');
                                res.send({ "Response": "Success", "Message": "Change form successfully submitted." });
                            }
                        });
                    }
                })
        }
    });
})
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM