Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This activity can be used in both microflows and nanoflows.

## Introduction

The **Commit object(s)** activity works on one or more objects. For persistable entities, committing an object stores it in the database. Committing non-persistable entities stores the current attribute values and association values in memory. This allows a rollback to revert to those values. See also [Persistability](/refguide/persistability/). External objects cannot be committed. To store changed values of external objects, use the [Send External Object](/refguide/send-external-object/) activity.
The **Commit object(s)** activity works on one or more objects. For persistable entities, committing an object writes it to the database. Committing non-persistable entities stores the current attribute values and association values in memory. This allows a rollback to revert to those values. See also [Persistability](/refguide/persistability/). External objects cannot be committed. To store changed values of external objects, use the [Send External Object](/refguide/send-external-object/) activity.

{{% alert color="info" %}}
A Mendix commit does not always behave like a database commit. See [How Commits Work](#how-commits-work), below, for more information.
Expand Down Expand Up @@ -105,15 +105,38 @@ When inside a [nanoflow](/refguide/nanoflows/), the object is refreshed across t

### Committing Objects

When you commit an object, the current value is saved. This means that you cannot roll back to the previous values of the object using the rollback object activity of a microflow.
When you commit an object, all changes to the current values are saved. This means that you cannot roll back to the previous values of the object using the **Rollback object** activity of a microflow.

However, a Mendix commit is not the same as a database commit. For an object of a persistable entity, the saved value is not committed to the database until the microflow and any microflows from which it is called, complete. This means that errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.
However, a Mendix commit is not the same as a database (SQL) COMMIT. When you use a **Commit object(s)** activity, Mendix actually performs an INSERT or UPDATE on the database. For an object of a persistable entity, the database COMMIT is not performed until the microflow and any microflows from which it is called, complete. This means that, although a retrieve from the database by the end-user's app will see the updated version of the object, the updated object will not be seen globally by other end-users until the microflows end.

Mendix mimics this behavior for non-persistable entities. Committing a non-persistable entity means that you cannot use a rollback object activity to go back to the previous values, although the rollback error handling in a microflow rolls back to the original values.
Another consequence of this is that, in contrast to an explicit **Rollback object** call, errors in a microflow can initiate a rollback. If a microflow activity errors and has **Error handling** set to **Rollback** or **Custom with rollback**, the value of the object is rolled back to the value it had at the start of the microflow. See [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for more information.

{{% alert color="warning" %}}
Deleting an object and then committing it can have different outcomes depending on whether the object has already been committed or not. If the object has already been committed, the delete will remove the object from the database, and the subsequent commit will have no effect. If the object is new (that is, it has not been committed before), the delete will do nothing, but the commit will store the object in the database. Therefore, this sequence of actions (a delete followed by a commit) may lead to unexpected results if the object has not been committed before.
{{% /alert %}}
#### What Gets Committed

When you work on an object in memory, Mendix records whether the object has been changed. When you perform a **Commit object(s)** activity, changes to the current values are written to the database and Mendix marks the object as unchanged in memory. This has a couple of consequences that you might not expect:

* If you commit an object which is then rolled back due to an error, committing the object again will not write the latest version to the database. You can understand this as the following sequence (see [Error Handling in Microflows](/refguide/error-handling-in-microflows/) for a more detailed discussion of how rollbacks work during error handling):

1. Your microflow starts and creates a savepoint.
1. You change your object – it is marked as changed.
1. You perform a **Commit object(s)** activity which sends the changes to the database – the object is marked as unchanged.
1. An error occurs after the **Commit object(s)** has successfully sent changes to the database, the microflow ends and data in the database is rolled back to the savepoint.
1. You perform a **Commit object(s)** on the object again, but the changes are not written to the database because:

* The object in memory still has your changes but it was marked as unchanged after your previous commit
* The **Commit object(s)** activity does not see the changed marker and so does not recognize that your object in memory has changes which need to be written.

If you want to keep the changes in the latest version you will have to work around this behavior.

* Deleting an object and then committing it has different outcomes depending on whether the object has already been committed or not:

* If the object has already been committed, the delete will remove the object from the database, and the subsequent commit will have no effect.
* If the object is new (that is, it has not been committed before), the delete will do nothing, but the commit will store the object in the database. Therefore, this sequence of actions (a delete followed by a commit) may lead to unexpected results if the object has not been committed before.


#### Committing Non-Persistable Entities

Mendix mimics this behavior for non-persistable entities. Committing a non-persistable entity means that you cannot use a rollback object activity to go back to the previous values, although the rollback error handling in a microflow rolls back to the original values.
Copy link
Contributor

Choose a reason for hiding this comment

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

I do not understand this part. Rollback on NPEs and PEs should work the same. After a commit the original values are replaced with the updated values, so a rollback will revert to the updated values. But that is the same for both NPEs and PEs.

Copy link
Member

Choose a reason for hiding this comment

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

A transaction rollback (which is what "the rollback error handling in a microflow" refers to) will rollback PEs to their original values from before the microflow, regardless of whether they were committed (as in commit object activity, not as in transaction commit).

Copy link
Contributor

Choose a reason for hiding this comment

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

I am not sure I understand @basdebakker but as far as I know, in general, nothing of the in-memory state of a mendix object is touched on a transaction commit or rollback. The two are independent.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Should we change this - I'm not sure how to make it clearer. I'm trying to say that PEs and NPEs work the same, but obviously I'm not being clear.

Copy link
Member

Choose a reason for hiding this comment

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

What @lvanengelen-mx is saying is just my point (I think). A transaction rollback will rollback any PEs to the state they were in before the transaction started. But it will not affect NPEs. So in that sense they are treated differently.

Copy link
Contributor

Choose a reason for hiding this comment

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

Bas and I came to the conclusion that we had a misunderstanding on what we meant with PE/NPE: state in memory vs state in the database.


### Autocommit and Associated Objects {#autocommit-and-associated-objects}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ This event can only be used in **Microflows**.
An error event defines where a microflow will stop and throw an error that occurred earlier. If you call a microflow, you may want to know whether any errors occurred within the microflow or not. This event throws the error again, so the caller of the microflow can catch them. When you use this event, all database actions within the current transaction will be rolled back (for more information, see [Error Handling in Microflows](/refguide/error-handling-in-microflows/)).

{{% alert color="warning" %}}
You can only use an error event if an error is in scope: Studio Pro does not accept it if you connect the normal execution flow to an error event, because there would not be an error to pass back to the caller.
You can only use an error event if an error is in scope: Studio Pro does not allow you to connect the normal execution flow to an error event, because there would not be an error to pass back to the caller.
{{% /alert %}}

In this example, an error occurs while committing an object to the database. It is caught, and the flow continues to the error event where the error is passed back to the caller of the microflow. So you can implement your error handling on multiple levels.
In the example below, an error flow is defined when committing an object to the database. Any error is caught, and the flow continues to the error event where the error is passed back to the caller of the microflow. This allows you to implement your error handling on multiple levels.

{{< figure src="/attachments/refguide/modeling/application-logic/microflows-and-nanoflows/events/error-event/error-event.png" class="no-border" >}}
{{< figure src="/attachments/refguide/modeling/application-logic/microflows-and-nanoflows/events/error-event/error-event.png" class="no-border" alt="A microflow with a parameter of 'MyEntity'. It has a single action committing 'MyEntity' which has an error flow ending in an error event and the normal flow ending in an end event" >}}

{{% alert color="info" %}}
When adding an error event, you need to add an [error handler](/refguide/error-handling-in-microflows/#errorhandlers) for an activity before the error event. Link an error event and an activity which has an error handlers set on it with a [sequence flow](/refguide/sequence-flow/) and select **Set as error handler** for the sequence flow.
Expand Down
Loading