I'm developing a plugin application for AutoCAD 2021 using the ObjectARX C#.Net framework. I'm trying to refactor it / make the code easier to understand at the moment, as I'll be returning to school soon and I'm currently the only full-time coder at my place of work.
I'm considering replacing a chunk of my code with a helper function so it can be reused in future AutoCAD projects, however it relies on IDisposable "transaction" objects to function at the moment.
If I call a function from within a transaction "using" statement, will it automatically make use of the transaction itself? Or, do I need to pass the transaction object to the function?
Edit: Including some sample code here.
using (Transaction trans0 = destDB.TransactionManager.StartTransaction())
{
//Setup for CSV Export, following code reads control panel, may be replaced with helper function that reads control panel
int grain = -1;
int thickness = 0;
int aCounter = 0;
int bCounter = 0;
String material = "NOTINITIALIZED";
//End setup
BlockTable destBT = trans0.GetObject(destDB.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord destBTR = trans0.GetObject(destBT[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
List<Entity> Containers = new List<Entity>();
List<Entity> Selectors = new List<Entity>();
List<Entity> SelectorFrames = new List<Entity>();
foreach (ObjectId id1 in destBTR)
{
Entity en = trans0.GetObject(id1, OpenMode.ForRead) as Entity;
if ((en.Layer.Equals("MDF")) || (en.Layer.Equals("PFM")) || (en.Layer.Equals("x")) || (en.Layer.Equals("y") || (en.Layer.Equals("ng"))))
{
SelectorFrames.Add(trans0.GetObject(id1, OpenMode.ForRead) as Entity);
}
if (en.Layer.Equals("selector"))
{
Selectors.Add(trans0.GetObject(id1, OpenMode.ForRead) as Entity);
}
if (en.Layer.Equals("Container"))
{
Containers.Add(trans0.GetObject(id1, OpenMode.ForRead) as Entity);
}
if (en.Layer.Equals("tCounter"))
{
thickness++;
}
if (en.Layer.Equals("aCounter"))
{
aCounter++;
}
if (en.Layer.Equals("bCounter"))
{
aCounter++;
}
}
foreach (Entity selector in Selectors)
{
using (Trimmer trimmer = new Autodesk.AutoCAD.ExportLayout.Trimmer())
{
foreach (Entity sFrame in SelectorFrames)
{
trimmer.Trim(selector, sFrame);
if (trimmer.EntityCompletelyInside)
{
if (sFrame.Layer.Equals("x"))
{
grain = 1;
}
else if (sFrame.Layer.Equals("y"))
{
grain = 2;
}
else if (sFrame.Layer.Equals("ng"))
{
grain = 0;
}
else
{
material = sFrame.Layer;
}
}
}
}
}
... some code that's in the same scope but not related to this proposed helper function ...
}
For most things, the answer would be "no": using
only impacts the lifetime of the object you're dealing with.
However, Transactions are kind of a special case. Creating and disposing a transaction causes certain state information to be associated with the current execution context, and many libraries have been written to detect and respect that state. So if your code calls into a method which then goes and performs database access, it's likely that the database access will be performed within the scope of that transaction.
You can find more details about how that works here. Things like how the static Transaction.Current
property gets set when you create a new transaction scope, how the transaction manager determines which transaction actions participate in, and how if necessary you can suppress the current transaction scope if you have code that needs to execute outside of whatever transaction is currently active.