我有几种方法的存储库,其中一些方法使用事务(.tx)。 例如,在下面的我的DevicesRepository中,“ add”方法必须插入一个新的Device,这意味着: 1.插入一个系统并返回ID(SystemsRepository) 2.插入带有返回器systemId的设备并获取新的ID 3.插入使用deviceId的其他片段(其他存储库)
我的问题是,在该事务中,我不知道如何访问其他回购方法。 我可以使用数据库对象中的其他存储库(Database.systems.add,Database.OtherRepo.add,[...]),但是如果我这样做了
在根数据库对象上调用该方法时,该方法从池中分配连接,执行回调,完成后-将连接释放回池中。但是,在另一个任务或事务中调用该方法时,该方法会重用父级连接。
一次执行多个请求时,一个请求只能分配和释放一次连接,同时在同一连接会话中执行所有必需的查询。更重要的是,交易只能在单个连接中进行。
谢谢! :)
P.S:我可以添加如何初始化数据库和存储库
./ db / repos / devices.js
'use strict';
var Database = null, pgp = null, Collections = null;
async function add(params) {
// I can use Database.systems.add
return Database.tx('Insert-New-Device', async function(transaction) {
let device = params.data.device;
const system = await transaction.systems.add(params);
device.systemid = system.systemId;
const query = pgp.helpers.insert(device, Collections.insert);
query += " RETURNING deviceId";
device.deviceId = await transaction.one(query);
const OtherRepoInsert = await transaction.otherRepos.add(params);
device.otherRepos.id = OtherRepoInsert.otherReposId;
return device
})
.then(data => { return data; })
.catch(ex => { throw new Error(ex); });
}
function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }
const DevicesRepository = {
add: add
};
module.exports = (db) => {
Database = db;
pgp = db.$config.pgp;
Collections = createColumnsets();
return DevicesRepository;
}
./ db / repos / systems.js
'use strict';
var Database = null, pgp = null, Collections = null;
async function add(params) {
var system = params.data.system;
system.archid=2;
system.distributionid=3;
var query = pgp.helpers.insert(system, Collections.insert);
if(params.return) query += " RETURNING *";
return Database.any(query)
.then(data => { return data; })
.catch(ex => { throw new Error(ex); });
}
function createColumnsets() { /* hidden for brevity (almost the same as the pg-promise-demo */ }
const SystemsRepository = {
add: add
};
module.exports = (db) => {
Database = db;
pgp = db.$config.pgp;
Collections = createColumnsets();
return SystemsRepository;
}
答案 0 :(得分:0)
我找到了真正的问题。
如果转到我的第一篇文章,您会看到我的每个仓库都导出了一个初始化函数: 1.由pg-promise'extend'事件调用 2.需要一个参数:上下文 3.使用此参数在db。$ config.pgp
中初始化存储库中的“ pgp”变量如demo中所述,当第一次在应用程序中以及每个任务和事务中加载数据库时,就会发生此事件。
就我而言: 事件第一次发生(完整的应用程序初始化)时,事件的参数'obj'是database context(包含$ config,$ pool等),因此可以正常工作 当事件发生在任务或事务中时,事件的参数'obj'是Task context,其中$ config不存在,因此事件无法使用我的存储库扩展上下文。引发了一个异常“无法读取未定义的属性帮助器”,但未出现并且不会使我的应用程序崩溃,我不知道为什么,也许是在事件中被捕获了。这就是为什么我不能在交易中使用我的仓库。
我像这样修改了我的代码,它起作用了:
./ db / index.js
'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
promiseLib: promise,
extend(obj, dc) {
obj.roles = repos.Roles(obj, pgp);
obj.shells = repos.Shells(obj, pgp);
obj.systems = repos.Systems(obj, pgp);
obj.devices = repos.Devices(obj, pgp);
}
};
const pgp = require('pg-promise')(initOptions);
const db = pgp(config);
/* hidden for brevity */
./ db / index.js
'use strict';
/* hidden for brevity */
// pg-promise initialization options:
const initOptions = {
promiseLib: promise,
extend(obj, dc) {
obj.roles = repos.Roles(obj, pgp);
obj.shells = repos.Shells(obj, pgp);
obj.systems = repos.Systems(obj, pgp);
obj.devices = repos.Devices(obj, pgp);
}
};
const pgp = require('pg-promise')(initOptions);
const db = pgp(config);
/* hidden for brevity */
./ db / repos / {repoFiles} .js
/* hidden for brevity */
module.exports = (db, pgpLib) => {
Database = db;
pgp = pgpLib;
Collections = createColumnsets();
return DevicesRepository;
}
答案 1 :(得分:0)
属性$config用于集成。这就是为什么它仅存在于根Database级别,而不存在于任务或事务内部的原因。
为了利用helpers命名空间,应在初始化存储库时将pgp
传递到存储库中,如pg-promise-demo所示:
extend(obj, dc) {
obj.users = new repos.Users(obj, pgp);
obj.products = new repos.Products(obj, pgp);
}
答案 2 :(得分:-1)
您可以在调用之外建立事务,然后将其传递给那些函数以使他们使用它。
也就是说,我建议您使用一个稍微高级的查询构建器库,例如Knex.js,以免于这些(以及将来)令人头疼的麻烦。