Here's my code
[CommandMethod(nameof(NestedTransactionsMissingEntity))]
public static void NestedTransactionsMissingEntity()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction trOuter = db.TransactionManager.StartTransaction())
{
// Create a line
Line l1 = new Line(new Point3d(0, 0, 0), new Point3d(10, 0, 0));
var btr = (BlockTableRecord)trOuter.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(l1);
trOuter.AddNewlyCreatedDBObject(l1, true);
using (Transaction trInner1 = db.TransactionManager.StartTransaction())
{
var extendsInner1 = trOuter.GetAllObjects();
var l2 = new Line(new Point3d(0 + 100, 0, 0), new Point3d(10 + 100, 0, 0));
btr.AppendEntity(l2);
trInner1.AddNewlyCreatedDBObject(l2, true);
trInner1.Commit(); //after commit then l2 should be in trOuter right?
}
using (Transaction trInner2 = db.TransactionManager.StartTransaction())
{
var extentsInner2 = trOuter.GetAllObjects(); //l2 not in trOuter? ditto for trInner2
var l3 = new Line(new Point3d(0 + 1000, 0, 0), new Point3d(10 + 1000, 0, 0));
btr.AppendEntity(l3);
trInner2.AddNewlyCreatedDBObject(l3, true);
trInner2.Commit(); //after commit then l3 should be in trOuter right?
}
var extentsOuter = trOuter.GetAllObjects(); // l2 and l3 not in trOuter?
trOuter.Commit();
}
ed.Regen();
}
You can see that the inner transaction committed entities ( l2 and l3) is not available after the fact in outer transaction. Why?
And how to ensure that they are available in outer transaction?
Solved! Go to Solution.
Solved by soonhui. Go to Solution.
Solved by _gile. Go to Solution.
@soonhui a écrit :
how to ensure that they are available in outer transaction?
As said in another topic, you should never use a DBObject outside of the the scope of the transaction this object has been added to because it has been disposed with this transcation.
@_gile , I'm not entirely sure what's your point relevance to my central question, namely
var extentsOuter = trOuter.GetAllObjects(); // l2 and l3 not in trOuter?
I would have expected that by that time the l2 and l3 are already in the object list in the trOuter ( because the inner transaction has been committed). This is the impression I got when I read this:
T1
...
T1->getAllObjects(); //only T1 objects
T2
...
T2->getAllObjects(); //only T2 objects
T1->getAllObjects(); //only T1 objects
T3
...
T3->getAllObjects(); //only T3 objects
T2->getAllObjects(); //only T2 objects
T1->getAllObjects(); //only T1 objects
end T3
T2->getAllObjects(); //both T2 and T3 objects
end T2
T1->getAllObjects(); //T1, T2 and T3 objects
end T1
@_gile , I'm confining my reply to this topic only-- no cross pollination. This topic has nothing to do with variable moving outer scope ( not from me anyway), just why GetAllObjects are not really getting the objects that have been committed in the previous inner transaction.
Transaction.GetAllObjects gets the objects opened or added to this transaction.
TransactionManager.GetAllObjects gets all objects from all transactions active.
[CommandMethod(nameof(NestedTransactions))]
public static void NestedTransactions()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var tm = db.TransactionManager;
void TransactionObjects(string name, Transaction tr) =>
ed.WriteMessage($"\n{name}: {string.Join(", ", tr.GetAllObjects().Cast<DBObject>().Select(e => e.GetType().Name))}");
void TransactionManagerObjects() =>
ed.WriteMessage($"\nTM: {string.Join(", ", tm.GetAllObjects().Cast<DBObject>().Select(e => e.GetType().Name))}");
using (Transaction t1 = tm.StartTransaction())
{
var currentSpace = (BlockTableRecord)t1.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
var line = new Line(new Point3d(-10.0, -10.0, 0.0), new Point3d(10.0, 10.0, 0.0));
currentSpace.AppendEntity(line);
t1.AddNewlyCreatedDBObject(line, true);
TransactionObjects("T1", t1);
TransactionManagerObjects();
using (var t2 = tm.StartTransaction())
{
var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0);
currentSpace.AppendEntity(circle);
t2.AddNewlyCreatedDBObject(circle, true);
TransactionObjects("T2",t2);
TransactionObjects("T1", t1);
TransactionManagerObjects();
using (var t3 = tm.StartTransaction())
{
var arc = new Arc(Point3d.Origin, 12.0, 0.0, Math.PI);
currentSpace.AppendEntity(arc);
t3.AddNewlyCreatedDBObject(arc, true);
TransactionObjects("T3", t3);
TransactionObjects("T2", t2);
TransactionObjects("T1", t1);
TransactionManagerObjects();
t3.Commit();
}
TransactionObjects("T2", t2);
TransactionManagerObjects();
t2.Commit();
}
TransactionObjects("T1", t1);
TransactionManagerObjects();
t1.Commit();
}
}
In addition to @_gile comment, here's a code snippet and comments that illustrates the relationship between nested transaction and the Abort() function
[CommandMethod(nameof(NestedTransactions))]
public static void NestedTransactions()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var tm = db.TransactionManager;
void TransactionObjects(string name, Transaction tr) =>
ed.WriteMessage($"\n{name}: {string.Join(", ", tr.GetAllObjects().Cast<DBObject>().Select(e => e.GetType().Name))}");
void TransactionManagerObjects() =>
ed.WriteMessage($"\nTM: {string.Join(", ", tm.GetAllObjects().Cast<DBObject>().Select(e => e.GetType().Name))}");
using var t1 = tm.StartTransaction();
var currentSpace = (BlockTableRecord)t1.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
var line = new Line(new Point3d(-10.0, -10.0, 0.0), new Point3d(10.0, 10.0, 0.0));
currentSpace.AppendEntity(line);
t1.AddNewlyCreatedDBObject(line, true);
TransactionObjects("T1", t1);
TransactionManagerObjects();
using (var t2 = tm.StartTransaction())
{
var circle = new Circle(Point3d.Origin, Vector3d.ZAxis, 10.0);
currentSpace.AppendEntity(circle);
t2.AddNewlyCreatedDBObject(circle, true);
TransactionObjects("T2", t2);
TransactionObjects("T1", t1);
TransactionManagerObjects();
using (var t3 = tm.StartTransaction())
{
var arc = new Arc(Point3d.Origin, 12.0, 0.0, Math.PI);
currentSpace.AppendEntity(arc);
t3.AddNewlyCreatedDBObject(arc, true);
TransactionObjects("T3", t3);
TransactionObjects("T2", t2); //still only 1 object for t2,
TransactionObjects("T1", t1);
TransactionManagerObjects();
t3.Commit();
}
TransactionObjects("T2", t2);//still only 1 object for t2. the objects added in the nested transaction t3 ( with or without commit) is not related to t2 per se.
TransactionManagerObjects(); //tm has 4 objects, 2 from t1, t3 and t2 contribute one each
t2.Abort(); //tm has only 2 objects from t1. t3 and t2 no more contributes.
}
TransactionObjects("T1", t1);
TransactionManagerObjects();
t1.Commit();
}
Can't find what you're looking for? Ask the community or share your knowledge.