Author Topic: Bricscad: Xrecord.Data throws InvalidOperationException  (Read 2071 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 601
Bricscad: Xrecord.Data throws InvalidOperationException
« on: March 15, 2017, 02:28:58 PM »
I use the following code below to get an xrecord from a drawing.  When I run the code in autocad I am able to access the xrecord.Data property and its value is nothing.  When i run it in Bricscad the property returns an InvalidOperationException.  The error happens at line 9 of the sample usage code.  Does anyone have any idea as to what might be wrong?  I have even tried creating a new result buffer and adding it to the xrecord before commiting the transaction but I still get the same error.


Code - Visual Basic: [Select]
  1. Private Const StressSystemsXRecordName = "StressSystems"
  2. Private Const StressWorxDictionaryName = "Stressworx"
  3. Private Const WorxApplicationName = "Worx_Plugins"
  4. Private ReadOnly _database As Database
  5. Private ReadOnly _document As Document
  6.  
  7. Public Function GetStressSystemIdFromMemory() As ObjectId
  8.         Dim id As ObjectId = Nothing
  9.         Dim worxApplicationDictionary As DBDictionary
  10.         Dim stressWorxDictionary As DBDictionary
  11.         Dim worxNodesXRecord As Xrecord
  12.         Using transaction = _database.TransactionManager.StartTransaction()
  13.                 Dim namedObjectDictionary As DBDictionary = transaction.GetObject(_database.NamedObjectsDictionaryId, OpenMode.ForRead)
  14.                 If namedObjectDictionary.Contains(WorxApplicationName) Then
  15.                         worxApplicationDictionary = namedObjectDictionary.GetAt(WorxApplicationName).OpenAs (Of DBDictionary)
  16.                 Else
  17.                         namedObjectDictionary.UpgradeOpen()
  18.                         worxApplicationDictionary = New DBDictionary()
  19.                         namedObjectDictionary.SetAt(WorxApplicationName, worxApplicationDictionary)
  20.                         transaction.AddNewlyCreatedDBObject(worxApplicationDictionary, True)
  21.                 End If
  22.  
  23.                 If worxApplicationDictionary.Contains(StressWorxDictionaryName) Then
  24.                         stressWorxDictionary = worxApplicationDictionary.GetAt(StressWorxDictionaryName).OpenAs (Of DBDictionary)
  25.                 Else
  26.                         worxApplicationDictionary.UpgradeOpen()
  27.                         stressWorxDictionary = New DBDictionary()
  28.                         worxApplicationDictionary.SetAt(StressWorxDictionaryName, stressWorxDictionary)
  29.                         transaction.AddNewlyCreatedDBObject(stressWorxDictionary, True)
  30.                 End If
  31.  
  32.                 If stressWorxDictionary.Contains(StressSystemsXRecordName) Then
  33.                         worxNodesXRecord = stressWorxDictionary.GetAt(StressSystemsXRecordName).OpenAs (Of Xrecord)(OpenMode.ForWrite)
  34.                 Else
  35.                         stressWorxDictionary.UpgradeOpen()
  36.                         worxNodesXRecord = New Xrecord()
  37.                         stressWorxDictionary.SetAt(StressSystemsXRecordName, worxNodesXRecord)
  38.                         transaction.AddNewlyCreatedDBObject(worxNodesXRecord, True)
  39.                 End If
  40.  
  41.                 id = worxNodesXRecord.ObjectId
  42.                 transaction.Commit()
  43.         End Using
  44.         Return Id
  45. End Function

Sample Usage

Code - Visual Basic: [Select]
  1. Public Function Deserialize() As StressSystemCollection
  2.         Dim stressSystemCollection = new StressSystemCollection()
  3.         Using _document.LockDocument()
  4.                 Using transaction = _database.TransactionManager.StartTransaction()
  5.                 try
  6.                                 Dim xrecordId = GetStressSystemXRecord()
  7.                                 Dim worxNodesXRecord = xrecordId.OpenAs(Of Xrecord)(OpenMode.ForRead)
  8.                                 If worxNodesXRecord IsNot Nothing
  9.                                         If worxNodesXRecord.Data IsNot Nothing
  10.                                                 Try
  11.                                                         stressSystemCollection = DeserializeFromNod(worxNodesXRecord.Data)
  12.                                                 Catch exception As System.Exception
  13.                                                         Active.WriteMessage(vbCrLf + "There was an error accessing the internal memory.  The memory has been cleared.")
  14.                                                 End Try
  15.                                         End If
  16.                                 End If
  17.                         Catch exception As System.Exception
  18.                         End Try
  19.  
  20.                         transaction.Commit()
  21.                 End Using
  22.         End Using
  23.         Return stressSystemCollection
  24. End Function
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Bricscad: Xrecord.Data throws InvalidOperationException
« Reply #1 on: March 16, 2017, 11:19:31 AM »
It appears that this is normal operation for Bricscad and for Teigha.  They appear to be throwing an error if you try to access the data without first setting it.  I do not believe that this is exceptional behavior and it should be just returning null instead.  However, this is easily fixed by creating an extension method that verifies that the xrecord has data on it.

Code - C#: [Select]
  1. public static class XrecordExtensions
  2. {
  3.         /// <summary>
  4.         /// Determines whether the specified xrecord has data.
  5.         /// </summary>
  6.         /// <param name="xrecord">The xrecord.</param>
  7.         /// <returns><c>true</c> if the specified xrecord has data; otherwise, <c>false</c>.</returns>
  8.         public static bool HasData(this Xrecord xrecord)
  9.         {
  10.                 try
  11.                 {
  12.                         if (xrecord.Data == null)
  13.                         {
  14.                                 return false;
  15.                         }
  16.                 }
  17.                 catch (InvalidOperationException)
  18.                 {
  19.                         return false;
  20.                 }
  21.  
  22.                 return true;
  23.         }
  24. }
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013