我们正在将我们的 api 从 C# 移植到 Loopback^v3.19.0
并遇到了一个阻止程序。
我们的许多模型都有共享属性,因此我们创建了一个基础模型“Base”,它们从中继承。
{
"name": "Base",
"base": "PersistedModel",
"idInjection": true,
"options": {
"validateUpsert": true
},
"mixins": {
"Timestamp": {}
},
"properties": {
"created-by": {
"type": "number",
"postgresql": {
"columnName": "created_by"
}
},
"created-date": {
"type": "date",
"postgresql": {
"columnName": "created_on_utc"
}
},
"updated-by": {
"type": "number",
"postgresql": {
"columnName": "updated_by"
}
},
"updated-date": {
"type": "date",
"postgresql": {
"columnName": "updated_on_utc"
}
},
"soft-deleted": {
"type": "boolean",
"postgresql": {
"columnName": "is_deleted"
}
},
"deleted-by": {
"type": "number",
"postgresql": {
"columnName": "deleted_by"
}
},
"deleted-date": {
"type": "date",
"postgresql": {
"columnName": "deleted_on_utc"
}
},
"tenant-id": {
"type": "number",
"postgresql": {
"columnName": "tenant_id"
}
}
},
...
}
在Timestamp mixin(我们自己的)中,相应地设置了这些属性
module.exports = function(Model, options) {
Model.observe('before save', function event(ctx, next) {
const token = ctx.options && ctx.options.accessToken;
const userId = token && token.userId;
const now = new Date().toISOString();
if (ctx.instance) {
ctx.instance['created-by'] = userId;
ctx.instance['created-date'] = now;
ctx.instance['updated-by'] = userId;
ctx.instance['updated-date'] = now;
} else {
if (ctx.data['soft-deleted'] &&
ctx.data['soft-deleted'] === true) {
ctx.data['deleted-by'] = userId;
ctx.data['deleted-date'] = now;
ctx.data['is-active'] = false;
}
ctx.data['updated-by'] = userId;
ctx.data['updated-date'] = now;
}
next();
});
};
这在创建新模型时非常有用。它对更新很有用,(PATCH /modelname/:id)
但意外坏了,我们不知道为什么。(这在从该模型继承的所有模型中都是一致的Base
。)
mixin 正确地看到模型并像这样添加更新的属性
LoopbackJS | ************* 'before save' ctx.data **************
LoopbackJS | { 'is-active': false,
LoopbackJS | 'updated-by': 1,
LoopbackJS | 'updated-date': '2018-08-16T17:57:23.660Z' }
LoopbackJS | ************* END 'before save' ctx.data **************
但是当环回执行更新 SQL 时,它会以某种方式忽略/删除updated-by
? (第二个参数应该是1
,不是null
)
LoopbackJS | 2018-08-16T17:57:23.666Z loopback:connector:postgresql SQL: UPDATE "public"."asset_types" SET "is_active"=$1,"updated_by"=$2,"updated_on_utc"=$3::TIMESTAMP WITH TIME ZONE,"tenant_id"=$4 WHERE "id"=$5
LoopbackJS | Parameters: [false,null,"2018-08-16T17:57:23.660Z",1,5]
updated_by
在 Postgres 中是可以为空的,所以不应该产生错误......但是 Loopback 正在发送一个字符串化的函数?
LoopbackJS | 2018-08-16T18:04:12.522Z loopback:connector:postgresql error: invalid input syntax for integer: "function () { [native code] }"
LoopbackJS | at Connection.parseE (/home/src/back-end/node_modules/pg/lib/connection.js:553:11)
LoopbackJS | at Connection.parseMessage (/home/src/back-end/node_modules/pg/lib/connection.js:378:19)
LoopbackJS | at TLSSocket.<anonymous> (/home/src/back-end/node_modules/pg/lib/connection.js:119:22)
LoopbackJS | at emitOne (events.js:115:13)
LoopbackJS | at TLSSocket.emit (events.js:210:7)
LoopbackJS | at addChunk (_stream_readable.js:264:12)
LoopbackJS | at readableAddChunk (_stream_readable.js:251:11)
LoopbackJS | at TLSSocket.Readable.push (_stream_readable.js:209:10)
LoopbackJS | at TLSWrap.onread (net.js:587:20)
如果我们不触及该updated_by
列,则 SQL 是正确的并会更新。
顺便说一句,如果我们软删除并且该deleted_by
列正在运行,那么同样的事情也会发生在那里。
感觉就像我在这里转圈子,可能忽略了一些基本的东西。有什么建议么?
编辑
所以看起来它不仅限于混合...当我们完全删除它并在有效负载中手动设置 k:v 对(即'created-by': 1
)时,我们仍然从 Postgres 得到相同的错误。