How Dynamo evaluates nodesI mentioned in my previous blog post that one of Dynamo's internal modes of interacting with the Revit API via Transactions is Manual Transaction mode, and Dynamo only evaluates in this mode when there is a Transaction node in the execution workflow. To summarize again: Dynamo starts evaluating the right-most nodes (nodes with nothing connected to the output). If a node has any inputs, then it first evaluates its inputs, and then passes the evaluated inputs to the node, which is then used to evaluate the node.
Take a look at the following image, in which I've labeled the order nodes are evaluated:
First, Dynamo tries to evaluate the Reference Point node. It sees that the node has an input, so it then tries to evaluate the input, which is the GraphFunction node. That also has inputs, so it start evaluating those, starting with the first (top-most). The multiplication node also has inputs, so it evaluates those. This brings us to the first Number node. It has no inputs, so it can be evaluated as-is. The number -1 is evaluated. Now the other input to the multiplication node needs to be evaluated. The pi node has no inputs, so it just returns 3.4159... Now, the inputs to the multiplication node are satisfied, and we can evaluate the node, which multiplies them. Dynamo will now start evaluating the second input to the GraphFunction node, and the same process will occur.
What the Transaction node doesThe Transaction node hooks into this evaluation tree-traversal in order to wrap some of the evaluation in a Revit API transaction. Let's say we had a Transaction node in between the division node and the GraphFunction node. When it would normally come time to attempt to evaluate the division node, it would first run into the new Transaction node. The Transaction node inserts some extra code in the process that initializes a new Revit API transaction, and the continues with the evaluation process. This means that the division node and its inputs will be evaluated with a transaction active. Once the division node has finished being evaluated, it's time for the Transaction node to be evaluated. For its evaluation, it ends the Transaction it created, and then passes its only input along as the result of the evaluation.
Caveats of the Transaction node
When a Transaction node is in the evaluation tree, Dynamo can no longer automatically manage the transactions of its nodes, since the user has explicitly determined when a transaction begins and--more importantly--ends. This means that any node which requires a transaction must be manually connected to a Transaction node by the user. This will prove to be rather inconvenient if you're using a third-party node that uses a transaction internally. However, it mirrors how writing any code for the Revit API involving transactions works, so if you're used to working with it in code, code with it in Dynamo should be familiar.
So when should I use a Transaction node?
Any time you need discreet control of a transaction in a Dynamo workflow. Without a Transaction node in the workflow, Dynamo will automatically detect if any of the nodes require a transaction, and if they do, it will run the entire workflow inside of one. If this functionality cannot accomplish what you need, that's when you use a Transaction node.
As mentioned in my previous blog post, a great example is the Solar Radiation Optimizer sample. It first adjust the value of a family instance parameter, then needs to recalculate the amount of incident solar radiation with the new value applied. The Solar Radiation plugin cannot recalculate until the parameter change has been applied, which requires the transaction the parameter change occurred in to have ended. When I wrote the Solar Radiation Optimizer sample, I used a Transaction node in order to set the new family instance parameter value. After the value was set, the transaction would end, the solar radiation plugin would update and spit out its results to a file, Dynamo would pick up on the change to the file and read in the new data, then compare the data with what it has stored, and then repeat the process until the end of the loop.