Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LC0054: Warning on database operations in TryFunctions #539

Open
wants to merge 4 commits into
base: prerelease
Choose a base branch
from

Conversation

StefanMaron
Copy link
Owner

No description provided.

@StefanMaron StefanMaron changed the title Development Add LC0054: Warning on database operations in TryFunctions Feb 12, 2024
@Arthurvdv
Copy link
Collaborator

Do not call write operations in try Functions
Do not call any database operations in TryFunctions.

There may be some ambiguity if all database operations should be avoided or only database write operations?

https://learn.microsoft.com/en-us/previous-versions/dynamicsnav-2018-developer/Handling-Errors-by-Using-Try-Functions#DbWriteTransactions

If I understand de documentation correctly, only database write operations should be avoided.
Maybe "Do not call any database write operations in TryFunctions." ?

@@ -95,6 +95,7 @@ Further note that you should have BcContainerHelper version 2.0.16 (or newer) in
|[LC0051](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0051)|Do not assign a text to a target with smaller size.|Warning|
|[LC0052](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0052)|The internal procedure is declared but never used.|Info|
|[LC0053](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0053)|The internal procedure is only used in the object in which it is declared. Consider making the procedure local.|Info|
|[LC0054](https://github.com/StefanMaron/BusinessCentral.LinterCop/wiki/LC0054)|Do not call any database operations in TryFunctions.|Warning|
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we specific mention write operations?

@@ -591,4 +591,13 @@
<data name="Rule0053InternalProcedureOnlyUsedInCurrentObjectAnalyzerTitle" xml:space="preserve">
<value>The internal method is only used in the object in which it is declared.</value>
</data>
<data name="Rule0054DatabaseOperationInTryFunctionsDescription" xml:space="preserve">
<value>Do not call write operations in try Functions</value>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to make this the same as the documentation?


private static readonly List<string> databaseInvocations = new List<string>
{
"insert", "delete", "modify", "modifyall", "rename", "addlink", "deletelink", "deletelinks", "commit"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add locktable

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need to take Rec.LockTable() into account, then we also should include Rec.ReadIsolation?

I do have a question about this do

Because changes made to the database by a try function are not rolled back, you should not include database write transactions within a try function

https://learn.microsoft.com/en-us/previous-versions/dynamicsnav-2018-developer/Handling-Errors-by-Using-Try-Functions#DbWriteTransactions

My first though is that a Rec.LockTable() doesn't created changes that could case issues when not rolled back. Do you have more insights or an example where this could cause an issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that below code should raise this warning

Rec.ReadIsolation := IsolationLevel::UpdLock;
Rec..FindFirst()

That is, IsolationLevel::UpdLock only causes a transaction if a read operation is called afterwards.

This can be even more complex, since the LockTable() or ReadIsolation could be called before the TryFunction is invoked, and a Find* operation is done inside the TryFunction. But I think that we could ignore that scenario, and focus on the 99.9% of cases 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But maybe that kind of transaction is no problem for TryFunctions? 🤔
I need to set up an environment with the DisableWriteInsideTryFunctions set, to repro this...

@jwikman
Copy link
Contributor

jwikman commented Feb 23, 2024

I just love the idea with this rule!

It is very challenging to find these issues during code review, since a TryFunction can call other functions that performs write operations.

@StefanMaron
Copy link
Owner Author

Yes, but I did not find a way to find those type of scenarios unfortunately

@jwikman
Copy link
Contributor

jwikman commented Feb 23, 2024

Yes, but I did not find a way to find those type of scenarios unfortunately

Ok, I see. But good to get started on this rule anyway!
Maybe we can update the rule one day, when we figure out how to... :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants