.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Inner Transaction committed entity not available?

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
soonhui
201 Views, 7 Replies

Inner Transaction committed entity not available?

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?

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software.

Read more at here

7 REPLIES 7
Message 2 of 8
cuongtk2
in reply to: soonhui

You must declare them in trOuter. Line l2 = null;

Message 3 of 8
_gile
in reply to: soonhui


@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.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 4 of 8
soonhui
in reply to: soonhui

@_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
##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software.

Read more at here

Message 5 of 8
_gile
in reply to: soonhui

Please, stop reply in one topic to the answers given in another topic, it makes boths topics unreadable separately.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 8
soonhui
in reply to: soonhui

@_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. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software.

Read more at here

Message 7 of 8
_gile
in reply to: soonhui

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();
    }
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 8 of 8
soonhui
in reply to: soonhui

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();
        }
##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software.

Read more at here

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report