Name a Transaction

Hi Community,

Quick question why i cannot set transaction name on this one.

TransactionManager.Instance.ForceCloseTransaction()
t = Transaction(doc, 'SetParameterValue')
t.Start()
for e in elements:
	for p, v in zip(parameters, values):
		e.SetParameterByName(p, v)
	output.append(e)
t.Commit()
#Assign your output to the OUT variable
OUT = output

and here’s the error message

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed.
Traceback (most recent call last):
File “”, line 50, in
Exception: Starting a new transaction is not permitted. It could be because another transaction already started and has not been completed yet, or the document is in a state in which it cannot start a new transaction (e.g. during failure handling or a read-only mode, which could be either permanent or temporary).

here’s a simple script where it’s failing.

Thanks in Advance.

Can you show the rest of your script?

   import clr
import sys
sys.path.append('C:\Program Files (x86)\IronPython 2.7\Lib')

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

import clr
clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
from System.Collections.Generic import *

import clr 
clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import * 

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager 

doc = DocumentManager.Instance.CurrentDBDocument
app = DocumentManager.Instance.CurrentUIApplication.Application
uiapp = DocumentManager.Instance.CurrentUIApplication

elements = IN[0]
parameters = IN[1]
values = IN[2]

output = []

if not isinstance(elements, list):
	elements = [elements]

if not isinstance(parameters, list):
	parameters = [parameters]

if not isinstance(values, list):
	values = [values]

TransactionManager.Instance.ForceCloseTransaction()
t = Transaction(doc, 'SetParameterValue')
t.Start()
for e in elements:
	for p, v in zip(parameters, values):
		
		e.SetParameterByName(p, v)
		
	output.append(e)
t.Commit()
#Assign your output to the OUT variable
OUT = output

I believe this line should be changed to:
TransactionManager.ForceCloseTransaction()

tried it and i got this error

Warning: IronPythonEvaluator.EvaluateIronPythonScript operation failed. 
Traceback (most recent call last):
  File "<string>", line 45, in <module>
TypeError: ForceCloseTransaction() takes exactly 1 argument (0 given)

You need to import the “transaction” module:

from Autodesk.Revit.DB import Transaction

But you should preferably not work with transactions this way rather using the transaction manager as described by Dimitar in this post:

This “works”

import clr
import sys
sys.path.append('C:\Program Files (x86)\IronPython 2.7\Lib')

clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
from Autodesk.Revit.DB import Transaction

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.Elements)
from System.Collections.Generic import *

clr.AddReference("RevitAPIUI")
from Autodesk.Revit.UI import * 

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager 

doc = DocumentManager.Instance.CurrentDBDocument

elements = IN[0]
parameters = IN[1]
values = IN[2]

output = []

if not isinstance(elements, list):
	elements = [elements]

if not isinstance(parameters, list):
	parameters = [parameters]

if not isinstance(values, list):
	values = [values]

t = Transaction(doc, 'Name')
t.Start()
output = "Success"
t.Commit()

OUT = output

image

2 Likes

still not working for me…hmmm

Thanks @erfajo

this is working great but what im after is to Name the actual transaction istead of this
image so i tried to follow the discussion here but nothing seems to work in this particular script. Not a big deal though just curious why it’snt working on this one :slight_smile:

that doesnt work

@myrwen.junterealSJC7 you are not going to be able to name the transaction using the TransactionManager object because that is currently not supported. You can read the source code implementation of that class and you will see in it a TransactionName variable set to a constant like so:

public static readonly string TransactionName = "Dynamo-51297CB5 Script";

@erfajo

Yes, that’s correct. Again looking at the source code at the link above you will discover two different transaction handling cases. One for Manual and one for Automatic. These are the two modes that Dynamo can be in:

image

Per those two modes, transaction is either commited (in manual mode) or it is simply kept open for the next run of Dynamo (automatic mode). I believe the reason why it is so, is to prevent a situation where Revit DB gets flooded with transaction commit requests so much that it crashes. So when Dynamo is in automatic, it won’t commit them all the time.

@myrwen.junterealSJC7 to name the transaction yourself you have to use the RevitAPI calls directly and skip the Dynamo wrappers. You can do that like so:

image

This will result in:

image

Pay special attention to the fact that I am using with statement here. Just like in C# with a using statement we are making sure to dispose of the transaction object when its done executing. Also, you will have to manually call Open and Commit to make sure that transactions are opened and closed.

Good luck!

7 Likes

Thank you very much @Konrad_K_Sobon for detailed explanation. Cheers!

@erfajo

I am not sure I can agree with this statement. Clearly there is a reason why Dynamo developers (people that are arguably much smarter and better at writing software), chose to do it this way over manually committing transactions on every run. Just think about it for a second:

You are in an Automatic mode in Dynamo so Dynamo graph re-executes every time there is a change happen, and that propagates downstream of the graph. Now imagine that you have multiple SetParameter nodes downstream, and each has t.Start() and t.Commit() in it. That’s asking Revit to start and commit multiple transactions per Dynamo graph iteration. Again, there is a huge possibility to flood the Revit DB and cause it to stall or crash.

Instead what they opted out to do, is consider this same scenario but with a slight different approach that would minimize calls to Revit DB. So we have the current Dynamo implementation that will not commit every transaction right away, but instead will keep it open. Similarly as above, let’s say there are multiple SetParameter nodes, and change happens upstream. This time however, as each node is executed, the transaction is not committed, instead it is kept open for the next node to add more changes to it. When they are all done, and all transaction actions are aggregated into a single large transaction, only then it is committed in a single call to Revit DB. That is much more efficient and arguably a better design pattern.

As much as I like to poke Dynamo Dev team, this is not something that I would pick a fight over.

4 Likes