Dear Experts,
I need your support to understand a strange behaviour about:
cds.transaction(req).run
this.transaction(req).run
I have problems with assert and update result done programmatically with these instructions.
1.ASSERT
I need to create an entity which must have input validation by ASSERT annotation (@assert.format and @assert.range).
By OData, everything is working fine. Result is an error due to assert “Value is not in specified format” or “Value is invalid according to enum declaration”.
If I do “CREATE” programmatically, asserts are not always checked.
By cds.transaction(req).run asserts are not checked and insert is done without error. (wrong behaviour !!)
By this.transaction(req).run asserts are checked and insert is not done. Errors are triggered. (correct behaviour)
2.UPDATE
Also update result has a different behaviour for CDS or THIS.
If I try to update a record which doesn’t exist in an entity:
By cds.transaction(req).run I get a variable with 0 value. (Preferred behavior)
By this.transaction(req).run I catch an error “not found”.
Both instructions are correct, but having a result in a variable is more convenient.
3.UPDATE and ASSERT together
3.1.ASSERT WRONG AND RECORD DOESN'T EXIST
I try to update a field with a wrong assert format in a record that doesn’t exist.
By cds.transaction(req).run I get a variable with 0 value because record doesn’t exist but no asserts are checked. (Partially wrong behaviour)
By this.transaction(req).run I catch multiple errors about assert: (correct behavior)
1. Value is invalid according to enum declaration
2. Value is not in specified format
3.2.ASSERT WRONG BUT RECORD EXIST
I try to update a field with a wrong assert format in a record that exist.
By cds.transaction(req).run record is updated without any error even if assert is wrong. (wrong behaviour!!)
By this.transaction(req).run I catch assert error “Value is not in specified format” (correct behavior)
I have created a repository with all above cases.
Below my release:
@sap/cds: 5.0.6
@sap/cds-compiler: 2.4.4
@sap/cds-dk: 4.0.7
@sap/cds-foss: 2.3.1
@sap/cds-runtime: 3.0.9
Node.js: v14.16.0
cap-assert-check: 1.0.0
Thank you in advance.
Best
Alice
Request clarification before answering.
Dear Kunz,
Thank you for you kindly replay.
I understand your explanation but I would prefere a different behaviour.
If I set some db checks, I would like that these checks are bloking.
I use a lot of APIs action to insert or update db data in order to avoid multiples OData calls from frontend. In this way the flow and the checks are managed by backend system.
If db checks do not work, I have to do them also programmaticaly.
For code consistency, it is more correct and maintainable to have control in a single point (annotation).
Is it possible to take into account my suggestion?
Maybe you could provide a parametrization to allow both behaviours.
Best.
Alice
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi david.kunz2,
thanks for your quick reply and your explanation.
I have only one doubt: why doesn't it recognize the anomalies related to the assert annotations through `cds.db.tx`?
Assert errors should also be caught by the database. For example @assert.unique is intercepted while @assert.format etc. no. (you can see the example in my repository).
Thank you in advance.
Alice
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Alice,
The reason for this is that we want to give application developers as much freedom as possible, you shouldn't be restricted too much if you run `await db.run(<whatever you want to do>)`. @assert.unique will be checked on the database itself (for performance reasons), so there's no real choice here. The other @assert annotations are only checked if the input comes from the user, there we will block the request as soon as possible so your handler can be sure that only valid input is given.
Best regards,
David
Hi alicegavanelli ,
The reason for this different behavior can be explained as follows:
`this` in your case is the application service (responsible for handling incoming OData/REST requests), if you perform `this.tx(...).run(...)`, then the application service handlers are called (which e.g. check for the assert annotations) and provided the results according to the result definition (e.g. 404 if you try to update a non-existent entity).
`cds.tx` is a shorthand for `cds.db.tx` and is the database service. If you run `cds.tx(...).run(...)` then the database handlers are called. Their response is a bit different to what the application service handlers would return.
We perform different things on the various layers.
Best regards,
David
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
| User | Count |
|---|---|
| 5 | |
| 4 | |
| 4 | |
| 3 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 | |
| 2 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.