Transaction Null Reference and eWasOpenforWrite Error

Transaction Null Reference and eWasOpenforWrite Error

drobertsY4GL3
Enthusiast Enthusiast
943 Views
2 Replies
Message 1 of 3

Transaction Null Reference and eWasOpenforWrite Error

drobertsY4GL3
Enthusiast
Enthusiast

I cannot seem to find a solution to getting the blockreference when inside an AttributeModifiedEventHandler. When using StartTransaction() I get a NullReferenceException and when using StartOpenCloseTransaction() I get a 'eWasOpenforWrite' error.

 

Please see below for further info and the event handler code.

 

Double clicking a dynamic block and selecting "OK" inside the enhanced attribute editor gives a NullReferenceException at:

using (Transaction transaction1 = transactionManager.StartTransaction())

Copying the dynamic block works however as expected.

 

If I change: StartTransaction() to:

using (var transaction1 = transactionManager.StartOpenCloseTransaction())

The attribute editor then works, but copying the block gives an 'eWasOpenForWrite' error at:

var blockReference = transaction1.GetObject(id, OpenMode.ForRead) as BlockReference;

Below is the full EventHandler.

private void AttributeModifiedEventHandler(object sender, Autodesk.AutoCAD.DatabaseServices.ObjectEventArgs args)
        {
            var transactionManager = currentDatabase.TransactionManager;

            AttributeReference attributeRef;
            string CadHandle = "";
            bool updateDB = false;

            if (args.DBObject is AttributeReference)
            {
                attributeRef = (AttributeReference)args.DBObject;

                using (Transaction transaction1 = transactionManager.StartTransaction())
                {                  
                    var blockTable = transaction1.GetObject(currentDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
                    var blockTableRecord = transaction1.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

                    foreach (ObjectId id in blockTableRecord)
                    {
                        // check if the current ObjectId is a block reference one
                        if (id.ObjectClass.DxfName == "INSERT")
                        {
                            var blockReference = transaction1.GetObject(id, OpenMode.ForRead) as BlockReference;


                            if (blockReference.Id == attributeRef.OwnerId)
                            {
                                CadHandle = blockReference.Handle.ToString();
                            }
                        };
                    }
                    transaction1.Commit();
                }
            }
        }

 

Any help anyone can give is extremely appreciated!

 

Thank you.

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

norman.yuan
Mentor
Mentor
Accepted solution

It looks to me that the purpose of the code in your AttributeModifiedEventHandler() does is to find the handle of attribute owner (blockreference) and assign it to a variable "CadHandle" (it also looks to me that the code in the eventhandler is not "full" - the local variable "CadHandle" is not used after being assigned value)

 

I do not understand is why you need to loop through entire ModelSpace for that while the agrs.DBObject has already had all information you need?

 

You can simply:

private void XXXXXXXHandler(object sender, ObjectEventArgs args)

{

  var att = args.DBObject As AttributeReference;

  if (att != null)

  {

    var CadHandle=att.OwnerId.Handle.ToString();

    // do something with CadHandle...

    // but do not attempt to modify anything in this event handler, in general

  }

}

Norman Yuan

Drive CAD With Code

EESignature

Message 3 of 3

drobertsY4GL3
Enthusiast
Enthusiast

Thank you Mr. Yuan.

This is my first AutoCAD plugin, so I am very grateful for the help. Your solution is a good clean example of how it should be done.

0 Likes