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

Creating Dictionary and Adding to Transaction

4 REPLIES 4
Reply
Message 1 of 5
matthewvclearspaninc
550 Views, 4 Replies

Creating Dictionary and Adding to Transaction

I keep getting the error "eNotNewlyCreated" on Transaction statements like the one in my code below. I am trying to add a dictionary (for storing xrecords) to an entity while inside of a transaction.  However, I only create this dictionary if the entity does not already have one.  I assume that this dictionary needs to be added to the transaction if (and only if) I had to create it (i.e. it did not already exist).  Is that accurate? Is this something that doesn't have to be added to the transaction after all?

 

/////snippet/////

                Boolean dictShouldBeAddedToTransaction = false;

                if (ent.ExtensionDictionary == null)
                {
                    dictShouldBeAddedToTransaction = true;
                }

                DBDictionary entDict = ACADExtensions.GetOrCreateExtensionDictionary(ent); //The entity now has a dictionary that can be written to

                trans.AddNewlyCreatedDBObject(entDict, dictShouldBeAddedToTransaction);

                String testKey = "Test Key";

                ACADExtensions.SetXDictionaryXrecordData(entDict,testKey, entDatatoAdd);

///////////////////

 

/////////snippet//////

public static DBDictionary GetOrCreateExtensionDictionary(this DBObject passedObj)
        {
            //Gets the passed object's dictionary if it exists, creates one if it does not
   
            if (passedObj.ExtensionDictionary == ObjectId.Null)
            {
                //A dictionary was not found in the passed DBObject
                passedObj.UpgradeOpen();
                passedObj.CreateExtensionDictionary();
            }
            return passedObj.ExtensionDictionary.GetObject<DBDictionary>();
        }

////////////////////////

 

 

 

 

 

4 REPLIES 4
Message 2 of 5
fixo
in reply to: matthewvclearspaninc

Try to use this working code example to your needs:

        [CommandMethod("SXD")]
        public void SetXdataToPolylines()
        {
            string regapp = "AppMaterial";
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            Matrix3d ucs = ed.CurrentUserCoordinateSystem;
            PromptSelectionOptions pso = new PromptSelectionOptions();

            pso.MessageForRemoval = "\nFailed to select polylines!";

            pso.MessageForAdding = "\nPlease, select the polylines on screen: ";

            // build filter to select polylines
            SelectionFilter filter =
                new SelectionFilter(new TypedValue[] { new TypedValue(0, "lwpolyline") });

            // perform block selection
            PromptSelectionResult res = ed.GetSelection(pso, filter);// might be SelectAll instead
            if (res.Status != PromptStatus.OK)
                return;
            ObjectIdCollection ids = new ObjectIdCollection(res.Value.GetObjectIds());

            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                RegAppTable rt = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
                if (rt.Has(regapp))
                {
                    RegAppTableRecord rtr =
                    (RegAppTableRecord)tr.GetObject(rt[regapp], OpenMode.ForWrite);
                }
                else
                {
                    rt.UpgradeOpen();
                    RegAppTableRecord rtr = new RegAppTableRecord();
                    rtr.Name = regapp;
                    rt.Add(rtr);
                    tr.AddNewlyCreatedDBObject(rtr, true);
                }
                foreach (ObjectId id in ids)
                {
                    Entity ent = (Entity)tr.GetObject(id, OpenMode.ForWrite, false);
                    Polyline pline = ent as Polyline;
                    if (pline != null)
                    {
                        Point3d p1 = pline.StartPoint.TransformBy(ucs);
                        Point3d p2 = pline.EndPoint.TransformBy(ucs);
                        double leg = Math.Round(pline.Length, 2);
                        string layer = pline.Layer;
                        double lsc = (double)pline.LineWeight;

                        TypedValue[] rb_values = {
                        new TypedValue(1001, regapp),
                        new TypedValue(1000, "Material Note"),
                        new TypedValue(1000,layer),
                        new TypedValue(1011, p1),
                        new TypedValue(1012, p2),
                        new TypedValue(1040, leg),
                        new TypedValue(1040, lsc)
                                                  };
                        ResultBuffer rb_xdata = new ResultBuffer(rb_values);
                        pline.XData = rb_xdata;
                        rb_xdata.Dispose();
                    }

                }

                tr.Commit();
            }
        }

        [CommandMethod("RXD")]
        static public void GetPolylinesXData()
        {
            Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            PromptSelectionOptions pso = new PromptSelectionOptions();

            pso.MessageForRemoval = "\nFailed to select polylines!";

            pso.MessageForAdding = "\nPlease, select the polylines on screen: ";

            // build filter to select polylines
            SelectionFilter filter =
                new SelectionFilter(new TypedValue[] { new TypedValue(0, "lwpolyline") });

            // perform block selection
            PromptSelectionResult res = ed.GetSelection(pso, filter);// might be SelectAll instead

            if (res.Status != PromptStatus.OK)
                return;
            ObjectIdCollection ids = new ObjectIdCollection(res.Value.GetObjectIds());

            Transaction tr = db.TransactionManager.StartTransaction();

            using (tr)
            {
                foreach (ObjectId id in ids)
                {
                    DBObject obj = tr.GetObject(id, OpenMode.ForRead) as DBObject;

                    ResultBuffer rb = obj.XData;

                    if (rb == null)
                    {
                        ed.WriteMessage("\nBlock does not have XData attached.");
                    }
                    else
                    {
                        ed.WriteMessage("\n-------------------------------------");

                        foreach (TypedValue tv in rb)
                        {
                            ed.WriteMessage(
                              "\nCode: {0}, Value: {1}", tv.TypeCode, tv.Value);
                        }
                        rb.Dispose();
                    }

                }

            }

        }

 

Message 3 of 5
matthewvclearspaninc
in reply to: fixo

My question is about creating a dictionary in an entity and then storing XRecord data to it , but the code you posted has to do with storing XData to the RegApp Table.  I'm not sure that is going to be useful here

Message 4 of 5

Hi,

 

Assuming you're using the extension methods from this thread, you do not need to check if the entity already have an extension dictionary, you do not need to add the extension dictionary to the entity, the SetXDictionaryXrecordData() extension method will do it (it calls GetOrCreateextensionDictionary()).


Extension methods can be called as instance methods of the extended type (DBObject here).

 

So, assuming ent is a DBObject opened in a transaction, entDatatoAdd is a ResultBuffer containing the data to set to the Xrecord, just replace all your first snippet with:

 

ent.SetXDictionaryXrecordData("Test Key", entDatatoAdd);

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5

Thank you, that is definitely a working solution.  However, I would still really like to understand why my approach didn't work.  Am I not just doing the exact same thing as SetXDictionaryXrecordData(args), but in 2 steps? It seems like there is still something I don't understand about transactions. Can anyone help straighten me out?

Tags (1)

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost