我正在尝试做我之前在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' }
这无疑表明我未正确执行交易。
有人能够帮助指导我如何改进和解决这个问题吗?
修改:对我的代码进行了更改以反映我找到的here,以及对我的第一次插入的一些更改。虽然我的第一个插件确实有效,但我仍然遇到上面的重复错误,所以现在我知道我的问题在于我如何在循环内部实现插入。有没有办法可以在每次插入时关闭连接?这是我应该尝试采取的方法吗?
答案 0 :(得分:0)
我最终得到它的工作,虽然我对一切工作原理的理解并没有得到很大改善,但我至少可以发布我所拥有的东西,希望其他人希望有所帮助。
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." });
}
});
}
})
}
});
})
});