Attach Object Data immediately after creating entity

Attach Object Data immediately after creating entity

Anonymous
Not applicable
3,229 Views
4 Replies
Message 1 of 5

Attach Object Data immediately after creating entity

Anonymous
Not applicable

Hi,

 

I am facing a strange problem with AutoCad.Net and Map 3d API.

I am creating a block inside a transaction block, add the newly created entity to modelspace and to transaction.AddNewlyCreatedDBObject(newEntity, true).

Immediately (before commiting the transaction) I am calling a method that attaches object data to the newly created entity. I am passing the objectid of the newly created entity to AddRecord of ODTable. Everything works fine without exceptions. Finally the transaction is committed. However the newly created block reference entity does not display in the editor, but I can select using QSelect. On saving the drawing, closing and re-opening the same drawing, the newly created block references are visible and the object data is intact (with values passed into AttachODData method).

What am I missing? What should I do to make the newly created blocks visible?

 

Below is the snippet of code

 

using(Transaction acTrans = currentDb.TransactionManager.StartTransaction())
{
using (BlockReference blkRef = new BlockReference(insPointValue, reducerBlockId))
{
blkRef.SetDatabaseDefaults();
Matrix3d currentUCS = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d coordSys = currentUCS.CoordinateSystem3d;
blkRef.TransformBy(Matrix3d.Rotation(rotation, coordSys.Zaxis, insPointValue));
modelSpace.AppendEntity(blkRef);
acTrans.AddNewlyCreatedDBObject(blkRef, true);
ODHelper.AttachObjectData(acadDoc, blkRef.ObjectId, ODTableName, columnsValues);
}
}

void AttachObjectData(Document acadDoc, ObjectId objId, string odTableName, Dictionary<string, object> columnsValues)
{
Table ODTable = GetODTable(acadDoc);
using (FieldDefinitions fieldDefs = ODtable.FieldDefinitions)
{
using (Records records = ODtable.GetObjectTableRecords(Convert.ToUInt32(0), objId,
Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, true))
{
if (0 == records.Count)
{
using (Record newRecord = Record.Create())
{
ODtable.InitRecord(newRecord);
PopulateFieldValues(ODtable.FieldDefinitions, newRecord, columnsValues);
ODtable.AddRecord(newRecord, objId);
}
}
else
{
using (OD.Record firstRecord = records[0])
{
PopulateFieldValues(ODtable.FieldDefinitions, firstRecord, columnsValues);
records.UpdateRecord(firstRecord);
}
}
}
}
}

else
{
using (OD.Record firstRecord = records[0])
{
PopulateFieldValues(ODtable.FieldDefinitions, firstRecord, columnsValues);
records.UpdateRecord(firstRecord);
}
}

}
}

}

 

0 Likes
3,230 Views
4 Replies
Replies (4)
Message 2 of 5

hgasty1001
Advisor
Advisor

Hi,

 

In the code you show, the transaction it's not being committed.

 

Gaston Nunez

 

 

0 Likes
Message 3 of 5

Anonymous
Not applicable

Thank you for the reply.

 

In the actual code I am committing the transaction. Missed it during copy / paste.

The newly inserted blocks and associated object data become visible after saving the drawing, closing and reopening the drawing. 

 

using(Transaction acTrans = currentDb.TransactionManager.StartTransaction())
{
Dictionary<string, object> columnValues = new Dictionary<string, object>();
columnValues.Add("FittingType", "Reducer");
// other field values omitted for brevity

Point3d insPointValue ; // Get the insertion point and rotation from the user
double rotation = 0.052359;
using (BlockReference blkRef = new BlockReference(insPointValue, reducerBlockId))
{
blkRef.SetDatabaseDefaults();
Matrix3d currentUCS = ed.CurrentUserCoordinateSystem;
CoordinateSystem3d coordSys = currentUCS.CoordinateSystem3d;
blkRef.TransformBy(Matrix3d.Rotation(rotation, coordSys.Zaxis, insPointValue));
modelSpace.AppendEntity(blkRef);
acTrans.AddNewlyCreatedDBObject(blkRef, true);
// acadDoc is a reference to the active document
ODHelper.AttachObjectData(acadDoc, blkRef.ObjectId, ODTableName, columnsValues);
}
acTrans.Commit();

editor.Regen();
}

 

 

 

 

 

void AttachObjectData(Document acadDoc, ObjectId objId, string odTableName, Dictionary<string, object> columnsValues)
{
Table ODTable = GetODTable(acadDoc, odTableName); // gets the object data table
using (FieldDefinitions fieldDefs = ODtable.FieldDefinitions)
{
using (Records records = ODtable.GetObjectTableRecords(Convert.ToUInt32(0), objId,
Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, true))
{
if (0 == records.Count)
{
using (Record newRecord = Record.Create())
{
ODtable.InitRecord(newRecord);
PopulateFieldValues(ODtable.FieldDefinitions, newRecord, columnsValues); // populate the ODRecord field values
ODtable.AddRecord(newRecord, objId);
}
}
else
{
using (OD.Record firstRecord = records[0])
{
PopulateFieldValues(ODtable.FieldDefinitions, firstRecord, columnsValues); // populate the ODRecord field values
records.UpdateRecord(firstRecord);
}
}
}
}
}

 

0 Likes
Message 4 of 5

norman.yuan
Mentor
Mentor

Yes, I can reproduce this issue if the creating new entity and attaching object data in single Transaction, like this:

 

using (var tran=database,TransactionManager.StartTRansaction())

{

     //Create a new entity

     ObjectId entId =CreateEntity(,,,);

    

    //Attach object data to this entity

    AttachObjectData(entId);

 

    tran.Commit();

}

 

When using AutoCAD MAP API to attach Object Data to entity, I believe the Map API manages the process in its own transaction. As outsiders, we do not know how the MAP API does it, thus not able to explain the above issue.

 

However, we can still write code to create entity and attach Object Data in "one step": creating the entity in a transaction, commit it and then attach data. Following code works as expected:

 

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using CadApp = Autodesk.AutoCAD.ApplicationServices.Application;

using Autodesk.Gis.Map;
using Autodesk.Gis.Map.ObjectData;

[assembly: CommandClass(typeof(EntityAndOdData.Commands))]

namespace EntityAndOdData
{
    public class Commands 
    {
        private const string OD_TABLE = "TestOD";

        [CommandMethod("NewOdEnt")]
        public static void RunMyCommand()
        {
            var dwg = CadApp.DocumentManager.MdiActiveDocument;
            var ed = dwg.Editor;

            try
            {
                var entId = CreateLine(dwg.Database);
                AttachOdData(dwg, entId);
ed.WriteMessage("\nOD data attached.\n"); } catch (System.Exception ex) { ed.WriteMessage("\nCommand failed:\n{0}", ex.Message); ed.WriteMessage("\n*Cancel*"); } } private static ObjectId CreateLine(Database db) { var entId = ObjectId.Null; using (var tran = db.TransactionManager.StartTransaction()) { var line = new Line( new Point3d(0.0, 0.0, 0.0), new Point3d(10.0, 10.0, 0.0)); line.SetDatabaseDefaults(db); var spaceId = SymbolUtilityServices.GetBlockModelSpaceId(db); var space = (BlockTableRecord) tran.GetObject(spaceId, OpenMode.ForWrite); entId = space.AppendEntity(line); tran.AddNewlyCreatedDBObject(line, true); tran.Commit(); } return entId; } private static void AttachOdData(Document dwg, ObjectId entId) { var mapProj = HostMapApplicationServices.Application.GetProjectForDB(dwg.Database); if (!mapProj.ODTables.IsTableDefined(OD_TABLE)) { dwg.Editor.WriteMessage( "\nOD Table {0} does not exist!\n", OD_TABLE); return; } var odTable = mapProj.ODTables[OD_TABLE]; using (var record = Record.Create()) { odTable.InitRecord(record); odTable.AddRecord(record, entId); } } } }

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 5 of 5

tamas.halasz
Enthusiast
Enthusiast

did anyone manage to find a solution for this?

0 Likes