I have a macro that is responsible of updating the block definition of a certain block by inserting the new block definition into the drawing database and then syncing the block references with the new definition.
Everything works fine, my only issue is that when I try to execute the macro twice or more on the same drawing, It crashes and outputs the error message below. But If I execute it once, save the drawing, close it, reopen it, and then reexecute the macro, it works. So the issue is that I can never execute the macro twice in a row on the same drawing during the same "opening".
I believe it got to do with the database memory/content not being updated/refreshed after the first run which affects the following executions, but I couldn't figure out how to resolve it.
************** Exception Text **************
Autodesk.AutoCAD.Runtime.Exception: eWasErased
at Autodesk.AutoCAD.DatabaseServices.TransactionManager.GetObjectInternal(AcDbTransactionManager* pTM, ObjectId id, OpenMode mode, Boolean openErased, Boolean forceOpenOnLockedLayer)
at Autodesk.AutoCAD.DatabaseServices.Transaction.GetObject(ObjectId id, OpenMode mode)
at EWasErased.Functions.<>c__DisplayClass3_0.<GetAttributesReference>b__0(ObjectId id) in P:\ingenierie\Menu AutoCAD MNS\EWasErased\Functions.cs:line 46
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.<OfTypeIterator>d__95`1.MoveNext()
at EWasErased.Class1.ResetAttributes(BlockReference blockReference, IEnumerable`1 attributeDefinitions, Transaction transaction) in P:\ingenierie\Menu AutoCAD MNS\EWasErased\Class1.cs:line 95
at EWasErased.Class1.SynchronizeAttributes(BlockTableRecord blockTableRecord, Transaction transaction) in P:\ingenierie\Menu AutoCAD MNS\EWasErased\Class1.cs:line 65
at EWasErased.Class1.SynchronizeBlockReferencesAttributes(Database db, String blockName) in P:\ingenierie\Menu AutoCAD MNS\EWasErased\Class1.cs:line 52
at EWasErased.Class1.CommandMethod() in P:\ingenierie\Menu AutoCAD MNS\EWasErased\Class1.cs:line 35
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
The macro code:
[CommandMethod("TEST")]
public static void CommandMethod()
{
Document document = Application.DocumentManager.MdiActiveDocument;
Database database = document.Database;
Editor editor = document.Editor;
string blockName = "8x11Materiel";
var blockFile = $@"{ResourcesFolderPath}\{blockName}.dwg";
using (var sourceDb = new Database(false, true))
{
sourceDb.ReadDwgFile(blockFile, FileOpenMode.OpenForReadAndAllShare, false, null);
database.Insert(blockName, sourceDb, false);
}
SynchronizeBlockReferencesAttributes(database, blockName);
editor.Regen();
}
public static void SynchronizeBlockReferencesAttributes(Database db, string blockName)
{
using Transaction transaction = db.TransactionManager.StartTransaction();
var blockTable = (BlockTable)transaction.GetObject(db.BlockTableId, OpenMode.ForRead);
if (!blockTable.Has(blockName))
{
return;
}
var blockDefinition = (BlockTableRecord)transaction.GetObject(blockTable[blockName], OpenMode.ForWrite);
SynchronizeAttributes(blockDefinition, transaction);
transaction.Commit();
}
public static void SynchronizeAttributes(BlockTableRecord blockTableRecord, Transaction transaction)
{
if (blockTableRecord == null)
throw new ArgumentNullException(nameof(blockTableRecord));
var attributeDefinitions = blockTableRecord.GetAttributesDefinition(transaction, OpenMode.ForRead);
if (attributeDefinitions == null || !attributeDefinitions.Any())
{
return;
}
foreach (BlockReference br in blockTableRecord.GetBlockReferences(transaction, OpenMode.ForWrite))
{
ResetAttributes(br, attributeDefinitions, transaction);
}
if (!blockTableRecord.IsDynamicBlock)
{
return;
}
blockTableRecord.UpdateAnonymousBlocks();
foreach (BlockTableRecord btr in blockTableRecord.GetAnonymousBlockDefinitions(transaction, OpenMode.ForWrite))
{
attributeDefinitions = blockTableRecord.GetAttributesDefinition(transaction, OpenMode.ForRead);
foreach (BlockReference br in btr.GetBlockReferences(transaction, OpenMode.ForWrite))
{
ResetAttributes(br, attributeDefinitions, transaction);
}
}
}
public static void ResetAttributes(BlockReference blockReference, IEnumerable<AttributeDefinition> attributeDefinitions, Transaction transaction)
{
if (blockReference == null)
throw new ArgumentNullException(nameof(blockReference));
if (attributeDefinitions == null)
throw new ArgumentNullException(nameof(attributeDefinitions));
var attributeValues = new Dictionary<string, string>();
foreach (AttributeReference attributeReference in blockReference.GetAttributesReference(transaction, OpenMode.ForWrite))
{
attributeValues
.Add(
attributeReference.Tag,
attributeReference.IsMTextAttribute ? attributeReference.MTextAttribute.Contents : attributeReference.TextString
);
attributeReference.Erase();
}
foreach (AttributeDefinition attributeDefinition in attributeDefinitions)
{
var attributeReference = new AttributeReference();
attributeReference.SetAttributeFromBlock(attributeDefinition, blockReference.BlockTransform);
blockReference.AttributeCollection.AppendAttribute(attributeReference);
blockReference.Database.TransactionManager.AddNewlyCreatedDBObject(attributeReference, true);
}
}