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