Problem with transactions to read records of Object Data of 3D polylines between 2 functions

Problem with transactions to read records of Object Data of 3D polylines between 2 functions

m.chavet7MJRB
Enthusiast Enthusiast
342 Views
2 Replies
Message 1 of 3

Problem with transactions to read records of Object Data of 3D polylines between 2 functions

m.chavet7MJRB
Enthusiast
Enthusiast

I've created a function that can be used on Civil3D (function 1), calling another function (function 2). This function calls another function that lists the existing ObjectData values of the "Profile" field of all the project's 3D polylines in a HashSet, then the idea is to make a selection of these polylines based on these different HashSet values successively.

The functions work independently of each other, but when I link them, they don't work anymore.

I think it's linked to the transactions. The records (OD fields) are correctly read in function 2, but when I want to read them again in my function 1, no record is detected and it's impossible to launch the "foreach (Record record in records2)" line, whereas before linking them, it worked.

 

 

 

 

 

 

    public class Fonctions_mineures
    {
        public static HashSet<string> listprofilepl()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            Tables tables = HostMapApplicationServices.Application.ActiveProject.ODTables;

            TypedValue[] filterList = new TypedValue[]
            {
            new TypedValue((int)DxfCode.Start, "POLYLINE")
            };

            SelectionFilter filter = new SelectionFilter(filterList);
            PromptSelectionResult psr = ed.SelectAll(filter);
            HashSet<String> ExistingProfile = new HashSet<String>();

            if (psr.Status == PromptStatus.OK)
            {
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {

                    foreach (SelectedObject so in psr.Value)
                    {
                        Autodesk.AutoCAD.DatabaseServices.Polyline3d ent = (Autodesk.AutoCAD.DatabaseServices.Polyline3d)tr.GetObject(so.ObjectId, OpenMode.ForRead);
                        Records records = tables.GetObjectRecords(0, ent, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false);

                        foreach (Record record in records)
                        {
                            for (int i = 0; i < record.Count; i++)
                            {
                                MapValue val = record[i];
                                Autodesk.Gis.Map.ObjectData.Table table = tables[record.TableName];
                                FieldDefinition fieldDef = table.FieldDefinitions[i];

                                if (fieldDef.Name == "Profile")
                                {
                                    ExistingProfile.Add(val.StrValue);
                                }
                            }
                        }
                        ExistingProfile.Remove("");
                        //tr.Commit();
                    }

                    return ExistingProfile;
                }
            }
            else
            {
                return ExistingProfile;
            }

        }
    }

    public class MyCommandsAEP
    {
        [CommandMethod("AEPFilterByObjectData")]

        public static void selectplbyvalue()
        {
            

            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            Tables tables = HostMapApplicationServices.Application.ActiveProject.ODTables;

            HashSet<string> profiles = Fonctions_mineures.listprofilepl();

            TypedValue[] filterList = new TypedValue[]{new TypedValue((int)DxfCode.Start, "POLYLINE")};
            SelectionFilter filter = new SelectionFilter(filterList);
            PromptSelectionResult psr = ed.SelectAll(filter);

            List<ObjectId> matchingPolylines = new List<ObjectId>();
            
            

            if (psr.Status == PromptStatus.OK)
            {

                Transaction tr2 = db.TransactionManager.StartTransaction();

                foreach (SelectedObject so in psr.Value)
                {
                    //Autodesk.AutoCAD.DatabaseServices.Polyline3d ent = tr.GetObject(so.ObjectId, OpenMode.ForRead) as Autodesk.AutoCAD.DatabaseServices.Polyline3d;

                    Autodesk.AutoCAD.DatabaseServices.Polyline3d ent = (Autodesk.AutoCAD.DatabaseServices.Polyline3d)tr2.GetObject(so.ObjectId, OpenMode.ForRead);
                    Records records2 = tables.GetObjectRecords(0, ent, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false);

                        // Votre logique de traitement pour les polylignes 2D
                    foreach (Record record in records2)
                    {
                        if (record != null)
                        {

                            foreach (string prof in profiles)
                            {

                                for (int i = 0; i < record.Count; i++)
                                {
                                    MapValue val = record[i];
                                    Autodesk.Gis.Map.ObjectData.Table table = tables[record.TableName];
                                    FieldDefinition fieldDef = table.FieldDefinitions[i];

                                    if (fieldDef.Name == "Profile" && val.StrValue == prof)
                                    {
                                        ed.WriteMessage($"\nEntity with ObjectId {so.ObjectId} has Profil value of {prof}.");
                                        matchingPolylines.Add(so.ObjectId);



                                        // Pour les fusionner

                                        //foreach (ObjectId vId in ent)
                                        //{
                                        //    PolylineVertex3d v3d = (PolylineVertex3d)tr.GetObject(vId, OpenMode.ForWrite);
                                        //    ent2.AppendVertex(v3d);
                                        //}
                                    }
                                }


                                ed.SetImpliedSelection(matchingPolylines.ToArray());
                            }
                        }
                        else
                        {
                            ed.WriteMessage("\nAucun enregistrement trouvé pour l'objet avec ObjectId: " + so.ObjectId.ToString());
                        }

                    }
                }

            }
        }

 

0 Likes
Accepted solutions (2)
343 Views
2 Replies
Replies (2)
Message 2 of 3

ActivistInvestor
Mentor
Mentor
Accepted solution

Your code has some problems with transactions. The command method starts a transaction but never commits or aborts it. The method that the command method calls starts a transaction but does not commit it and instead allows it to be aborted by the using directive.

 

If you start a transaction and do not either commit or abort it, and do not call Dispose() on it the transaction will remain active until the managed runtime reclaims it in a subsequent garbage collection. At that point, the still-active transaction will be aborted which may happen long after your command has finished executing.

 

You should always control the life of a transaction with a Using directive and ensure it is committed even if you don't make any changes to the database. A transaction should only be aborted if a failure occurs that halts execution of your code before it has finished doing its work.

0 Likes
Message 3 of 3

norman.yuan
Mentor
Mentor
Accepted solution

Besides what @ActivistInvestor said, in your CommandMethod, there is no need to start a Transaction at all: most AutoCAD MAP's ObjectData API methods manage transaction internally. In your case, for reading object data with method Table.GetObjectRecords(), you do not have to pass in a Acad entity opened from a Transaction; instead, you can pass the ObjectId of the target entity.

 

    foreach (SelectedObject so in psr.Value)
    {
        using (var records2 = tables.GetObjectRecords(0, so.ObjectId, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false)
        {
           // find the wanted OD data value from the OD record
        }
    }

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes