43
Today, the only way to wrap transactional code in a "Try/Catch"-esque manner is by using
"If codeunit.run() then"

This has a couple of weird ancient quirks that result in a mix of worse performance, worse readability and more footguns for new AL developers.

Problems:
1. You cannot have an active transaction going before invoking it. There is no good technical reason for this limitation.
2. when it returns true, it has an implicit commit. This is a common footgun, even BC developers with 10+ years experience get surprised by that one.
3. It can only handle one record parameter.
4. OnRun is a "magic" trigger requiring a new codeunit, every time one is needed.

Suggestion:
Expand the TryFunction with a parameter "AllowTransactions" (bool), with default value false for backwards compatibility like this:

[TryFunction(true)]
ThisFunctionIsAMoreErgonomicCodeunitRunTrigger(Param1: Text; Param2: Integer)

If you leave out the old limitations described above in 1) and 2), but leave the forced rollback upon error it would behave like a more intuitive and more flexible Codeunit.Run() construct.

Side bonus: There has been suggestions in the community to add Rollback() to AL. This would be solved indirectly with this construct as one could do:
[TryFunction(true)]
Rollback()
begin
Error('');
end;

as it would be invokeable from inside a transaction, as opposed to "If Codeunit.Run() then"
Category: Development
STATUS DETAILS
Needs Votes
Ideas Administrator

Thank you for this suggestion! Currently this is not on our roadmap. We are tracking this idea and if it gathers more votes and comments we will consider it in the future. Best regards, Business Central Team

Comments

M

You could consider using a background session instead.

Category: Development

M

Vjeko did a good write-up of this in 2015 - noting that we already have some ability to nest SQL transactions through TestIsolation


Fixing Preview Posting: Part 2 – Vjeko.com


Category: Development

M

I vote 10,000% for this. The `if Codeunit.Run()` pattern requires a tonne of boilerplate code, which is easy to write wrong, copy/paste wrong, etc. - to wrap the actual function, setting up its 'arguments', and getting out its results. It also wastes a codeunit ID, or requires some really complicated 'Try codeunits' that contain lots of globals - again simply inviting bugs later.


AL developers who know what we're doing, and sure - know the limitations of even `if Codeunit.Run()` - could opt-in to this new `[TryFunction(ActLikeIfCodeunitRun := true)]` behaviour and avoid having to waste so much time and IDs on boilerplate.

Category: Development

M

Note: This would also fix the gap left behind by the removal of the ASSERTERROR hack used by some partners in production C/AL code.

Category: Development