Page 2 of 2 FirstFirst 12
Results 11 to 20 of 20

Thread: Save structured data in an entity

  1. #11
    100 Club
    Join Date
    2002-10
    Posts
    154
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    that sample came from http://through-the-interface.typepad...circles_1.html

    What types of ojbects can a dictionalry hold? I know of other Dictionaries or xRecords.

    The ResultBuffer is held in xRecords.Data.

  2. #12
    Woo! Hoo! my 1st post
    Join Date
    2010-05
    Posts
    1
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    You can also save DataTable objects in dictionaries:
    NamedObjsDict.SetAt(String Name, Autodesk.AutoCAD.DatabaseServices.DataTable)

  3. #13
    AUGI Addict fixo's Avatar
    Join Date
    2005-05
    Location
    Pietari, Venäjä
    Posts
    1,269
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    Welcome on board!
    Good point
    Here is some code how to manage it
    http://forums.augi.com/showpost.php?...52&postcount=1

  4. #14
    I could stop if I wanted to
    Join Date
    2003-03
    Location
    Alberta
    Posts
    260
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    A trick I also use is to use XML serialization to store custom data in an Xrecord. In short I have a custom class that holds data, I serialize it into a memory stream, turn it into a compressed/encrypted string of bytes and store them in the Xrecord. Only down side is if I have pointers to ObjectIds, I have to add addtional ResultBuffers to account for them and handle them when decoding the data.

  5. #15
    AUGI Addict
    Join Date
    2015-12
    Posts
    2,095
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    Quote Originally Posted by bweir View Post
    A trick I also use is to use XML serialization to store custom data in an Xrecord. In short I have a custom class that holds data, I serialize it into a memory stream, turn it into a compressed/encrypted string of bytes and store them in the Xrecord. Only down side is if I have pointers to ObjectIds, I have to add addtional ResultBuffers to account for them and handle them when decoding the data.
    Slick. Could even leave it as an XML fragment stored as a string provided its not too long.

  6. #16
    Member
    Join Date
    2005-05
    Posts
    18
    Login to Give a bone
    0

    Question Re: Save structured data in an entity

    I was trying to do this same thing based on a document from Autodesk University 2008 by Jeffery Geer (A Pattern for Storing Structured Data in AutoCAD Entities CP401-2).

    It got me pretty far down the road:

    I have polyline that graphically represents a pipe. Obviously, the polyline can not contain data for a pipe: size, material, insulationtype, insulationthickness, schedule, etc. So, I have created a custom object with all of the appropriate properties, methods, events, etc that I need for it to behave as a pipe. My custom object has a reference to the actual polyline with a Handle property stored as a long(since AutoCAD objects can not be serialized).

    My object is marked serializable. I serialize it to binary and attach the binary in 127 byte chunks to the xRecord of the polyline object. My code works AWESOME!!! Thanks Jeffery.

    However, as soon as I attach this binary xrecord, I get the following message when I try to save the drawing:

    "One or more objects in this drawing cannot be saved to the specified format. The operation was not completed and no file was created”

    I assume that since this was an AU course that some one has tried this at some point and knows how to bypass this error, but I can not find anyone willing to admit it. Does anyone here want to stake a claim to my praise?

  7. #17
    I could stop if I wanted to
    Join Date
    2003-03
    Location
    Alberta
    Posts
    260
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    I've had similar issues, it is usually traced back to some transaction or other object not being disposed of correctly. Look through your code closely (in VB.NET use the Using... End Using syntax whenever possible) and be sure you make use of the proper transaction type. I've caught my self using the OpenCloseTransaction a few times where I should not be. I blame it on intellisence

  8. #18
    100 Club
    Join Date
    2002-10
    Posts
    154
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    I have tried disposing all objects, I have tried to have "using" everywhere that it would accept it. I even tried the XmlSerializer. I still can't save once I have placed something in the dictionaries.

    Any suggestiosn would be appreciated.

    Code:
            <System.Xml.Serialization.XmlRootAttribute("xValue", Namespace:="http://www.cpandl.com", IsNullable:=False)> _
    Public Class xValue
           Public Name As String
           Public Value As String
    End Class
    Public Shared Sub Write(_DictName As String, _SubDictName As String, _XRecordName As String, _WriteValue As String)
                Dim _xValue As New xValue
                _xValue.Name = _XRecordName
                _xValue.Value = _WriteValue
                Using stream As New MemoryStream()
                    Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(xValue))
                    serializer.Serialize(stream, _xValue)
                    stream.Position = 0
                    Using reader As TextReader = New StreamReader(stream)
                        Dim xmlString As String = reader.ReadToEnd()
                        Dim data As New ResultBuffer()
    
                        data.Add(New TypedValue(CInt(DxfCode.Text), _xValue.[GetType]().FullName))
                        While xmlString.Length > 0
                            Dim buffer As String = ""
                            If xmlString.Length >= 1024 Then
                                buffer = xmlString.Substring(0, 1024)
                                xmlString = xmlString.Substring(1024)
                            Else
                                buffer = xmlString
                                xmlString = ""
                            End If
                            data.Add(New TypedValue(CInt(DxfCode.Text), buffer))
                        End While
    
                        '' Get the current document and database
                        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
                        Dim acCurDb As Database = acDoc.Database
    
                        '' Start a transaction
                        Using doclock As DocumentLock = acDoc.LockDocument
                            Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
                                Try
                                    Using mDict As DBDictionary = GetDict(acCurDb, acTrans, _DictName)
                                        If mDict Is Nothing Then
                                            MsgBox("Dictionary does not exist")
                                        Else
                                            If Not mDict.Contains(_SubDictName) Then mDict.SetAt(_SubDictName, New DBDictionary)
    
                                            Using SubDict As DBDictionary = CType(acTrans.GetObject(mDict.GetAt(_SubDictName), OpenMode.ForRead), DBDictionary)
                                                If Not SubDict.Contains(_XRecordName) Then SubDict.SetAt(_XRecordName, New Xrecord)
    
                                                Using xRec As Xrecord = CType(acTrans.GetObject(SubDict.GetAt(_XRecordName), OpenMode.ForWrite), Xrecord)
                                                    '                        xRec.Data = GetBufferFromList(itm, _XRecordName)
                                                    'Dim Buff As New ResultBuffer
                                                    'For Each mSt As String In _WriteValues
                                                    '    Buff.Add(New TypedValue(DxfCode.Text, mSt))
                                                    'Next
                                                    xRec.Data = data
                                                    SubDict.SetAt(_XRecordName, xRec)
                                                    acTrans.Commit()
                                                End Using
                                            End Using
                                        End If
                                    End Using
                                Catch ex As System.Exception
                                    acDoc.Editor.WriteMessage(ex.Message & vbLf & ex.StackTrace)
                                End Try
                            End Using
                        End Using
                    End Using
                End Using
            End Sub
    
    
            Public Shared Function Read(_DictName As String, _SubDictName As String, _XRecordName As String) As String
                Dim ReadVal As String
                Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(xValue))
    
                '' Get the current document and database
                Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
                Dim acCurDb As Database = acDoc.Database
    
                '' Start a transaction
                Using doclock As DocumentLock = acDoc.LockDocument
                    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
                        Try
                            If DictExists(acCurDb, acTrans, _DictName) Then
                                Using mDict As DBDictionary = GetDict(acCurDb, acTrans, _DictName)
                                    If mDict.Contains(_SubDictName) Then
                                        Using SubDict As DBDictionary = CType(acTrans.GetObject(mDict.GetAt(_SubDictName), OpenMode.ForRead), DBDictionary)
                                            If SubDict.Contains(_XRecordName) Then
                                                Dim xRec As Xrecord = CType(acTrans.GetObject(SubDict.GetAt(_XRecordName), OpenMode.ForWrite), Xrecord)
                                                '                                   Dim First As Boolean = True
                                                'For Each tval As TypedValue In xRec.Data
                                                '    If ReadVal Is Nothing Then ReDim ReadVal(0 To 0) Else ReDim Preserve ReadVal(0 To ReadVal.Count)
                                                '    ReadVal(UBound(ReadVal)) = tval.Value
                                                '    '                                        First = False
                                                'Next
                                                Using rb As ResultBuffer = xRec.Data
                                                    If rb IsNot Nothing Then
                                                        Using stream As New MemoryStream()
                                                            Dim tvs As TypedValue() = rb.AsArray()
                                                            If tvs IsNot Nothing Then
                                                                If tvs(0).TypeCode = CShort(DxfCode.Text) Then
                                                                    Dim xmlString As String = ""
                                                                    Dim writer As TextWriter = New StreamWriter(stream)
                                                                    For i As Integer = 1 To tvs.Length - 1
                                                                        If tvs(i).TypeCode = CShort(DxfCode.Text) Then
                                                                            xmlString = DirectCast(tvs(i).Value, String)
                                                                            writer.Write(xmlString)
                                                                        End If
                                                                    Next
                                                                    writer.Flush()
                                                                    stream.Position = 0
                                                                    ReadVal = TryCast(serializer.Deserialize(stream), xValue).Value
                                                                End If
                                                            End If
                                                        End Using
                                                    End If
                                                End Using
                                            End If
                                        End Using
                                    End If
                                End Using
                            End If
                        Catch ex As System.Exception
                            acDoc.Editor.WriteMessage(ex.Message & vbLf & ex.StackTrace)
                        End Try
                    End Using
                End Using
    
                Return ReadVal
            End Function

  9. #19
    Active Member
    Join Date
    2009-08
    Posts
    93
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    You do not need the using statement for those objects you open with a transaction.
    You do need to commit the transaction.
    Add a acTrans.Commit() before its End Using and see if that works.

  10. #20
    AUGI Addict fixo's Avatar
    Join Date
    2005-05
    Location
    Pietari, Venäjä
    Posts
    1,269
    Login to Give a bone
    0

    Default Re: Save structured data in an entity

    I've tested your code after changes as Jeff mentioned above,
    looks like it's working with no problems on my A2010,
    here is a complete code I've used:
    Code:
       
    
    Public Class XdataSerialize
        <System.Xml.Serialization.XmlRootAttribute("xValue", Namespace:="http://www.cpandl.com", IsNullable:=False)> _
        Public Class xValue
            Public Name As String
            Public Value As String
        End Class
        Public Shared Function DictExists(db As Database, tr As Transaction, ByVal dictname As String) As Boolean
            Dim isexist As Boolean = False
    
            Using (tr)
                Dim nod As DBDictionary = TryCast(tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead), DBDictionary)
                If nod Is Nothing Then
                    isexist = False
                End If
                Dim id As ObjectId = ObjectId.Null
                Try
                    id = nod.GetAt(dictname)
                    Dim dict As DBDictionary = TryCast(tr.GetObject(id, OpenMode.ForRead), DBDictionary)
                    If dict Is Nothing Then
                        isexist = False
                    Else
                        isexist = True
                    End If
                Catch ex As Exception
                    isexist = False
                End Try
            End Using
            Return isexist
        End Function
        Public Shared Function GetDict(db As Database, tr As Transaction, ByVal dictname As String) As DBDictionary
            Dim dict As New DBDictionary
    
            Using (tr)
                Dim nod As DBDictionary = TryCast(tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead), DBDictionary)
                If nod Is Nothing Then
                    Return Nothing
                End If
                Dim id As ObjectId = ObjectId.Null
                Try
                    id = nod.GetAt(dictname)
                    dict = TryCast(tr.GetObject(id, OpenMode.ForRead), DBDictionary)
                    If dict Is Nothing Then
                        Return Nothing
                    Else
                        Return dict
                    End If
                Catch ex As Exception
                    Return Nothing
                End Try
            End Using
    
        End Function
    
        Public Shared Sub Write(_DictName As String, _SubDictName As String, _XRecordName As String, _WriteValue As String)
            Dim xmlString As String
            Dim _xValue As New xValue
            _xValue.Name = _XRecordName
            _xValue.Value = _WriteValue
            Using stream As New MemoryStream()
                Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(xValue))
                serializer.Serialize(stream, _xValue)
                stream.Position = 0
                Using reader As TextReader = New StreamReader(stream)
                    xmlString = reader.ReadToEnd()
                End Using
                Dim data As New ResultBuffer()
    
                data.Add(New TypedValue(CInt(DxfCode.Text), _xValue.[GetType]().FullName))
                While xmlString.Length > 0
                    Dim buffer As String = ""
                    If xmlString.Length >= 1024 Then
                        buffer = xmlString.Substring(0, 1024)
                        xmlString = xmlString.Substring(1024)
                    Else
                        buffer = xmlString
                        xmlString = ""
                    End If
                    data.Add(New TypedValue(CInt(DxfCode.Text), buffer))
                End While
    
                '' Get the current document and database
                Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
                Dim acCurDb As Database = acDoc.Database
    
                '' Start a transaction
                Using doclock As DocumentLock = acDoc.LockDocument
                    Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
                        Try
                            Dim mDict As DBDictionary = GetDict(acCurDb, acTrans, _DictName)
                            If mDict Is Nothing Then
                                MsgBox("Dictionary does not exist")
                            Else
                                If Not mDict.Contains(_SubDictName) Then mDict.SetAt(_SubDictName, New DBDictionary)
    
                                Dim SubDict As DBDictionary = DirectCast(acTrans.GetObject(mDict.GetAt(_SubDictName), OpenMode.ForRead), DBDictionary)
                                If Not SubDict.Contains(_XRecordName) Then SubDict.SetAt(_XRecordName, New Xrecord)
    
                                Dim xRec As Xrecord = DirectCast(acTrans.GetObject(SubDict.GetAt(_XRecordName), OpenMode.ForWrite), Xrecord)
                                '                        xRec.Data = GetBufferFromList(itm, _XRecordName)
                                'Dim Buff As New ResultBuffer
                                'For Each mSt As String In _WriteValues
                                '    Buff.Add(New TypedValue(DxfCode.Text, mSt))
                                'Next
                                xRec.Data = data
                                SubDict.SetAt(_XRecordName, xRec)
                                acTrans.Commit()
                                
                            End If
    
                        Catch ex As System.Exception
                            acDoc.Editor.WriteMessage(ex.Message & vbLf & ex.StackTrace)
                        End Try
                    End Using
                End Using
    
            End Using
        End Sub
    
    
        Public Shared Function Read(_DictName As String, _SubDictName As String, _XRecordName As String) As String
            Dim ReadVal As String = String.Empty
            Dim serializer As New System.Xml.Serialization.XmlSerializer(GetType(xValue))
    
            '' Get the current document and database
            Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim acCurDb As Database = acDoc.Database
    
            '' Start a transaction
            Using doclock As DocumentLock = acDoc.LockDocument
                Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
                    Try
                        If DictExists(acCurDb, acTrans, _DictName) Then
                            Dim mDict As DBDictionary = GetDict(acCurDb, acTrans, _DictName)
                            If mDict.Contains(_SubDictName) Then
                                Dim SubDict As DBDictionary = CType(acTrans.GetObject(mDict.GetAt(_SubDictName), OpenMode.ForRead), DBDictionary)
                                If SubDict.Contains(_XRecordName) Then
                                    Dim xRec As Xrecord = CType(acTrans.GetObject(SubDict.GetAt(_XRecordName), OpenMode.ForWrite), Xrecord)
                                    '                                   Dim First As Boolean = True
                                    'For Each tval As TypedValue In xRec.Data
                                    '    If ReadVal Is Nothing Then ReDim ReadVal(0 To 0) Else ReDim Preserve ReadVal(0 To ReadVal.Count)
                                    '    ReadVal(UBound(ReadVal)) = tval.Value
                                    '    '                                        First = False
                                    'Next
                                    Dim rb As ResultBuffer = xRec.Data
                                    If rb IsNot Nothing Then
                                        Using stream As New MemoryStream()
                                            Dim tvs As TypedValue() = rb.AsArray()
                                            If tvs IsNot Nothing Then
                                                If tvs(0).TypeCode = CShort(DxfCode.Text) Then
                                                    Dim xmlString As String = ""
                                                    Dim writer As TextWriter = New StreamWriter(stream)
                                                    For i As Integer = 1 To tvs.Length - 1
                                                        If tvs(i).TypeCode = CShort(DxfCode.Text) Then
                                                            xmlString = DirectCast(tvs(i).Value, String)
                                                            writer.Write(xmlString)
                                                        End If
                                                    Next
                                                    writer.Flush()
                                                    stream.Position = 0
                                                    ReadVal = TryCast(serializer.Deserialize(stream), xValue).Value
                                                End If
                                            End If
                                        End Using
                                    End If
    
                                End If
    
                            End If
    
                        End If
                    Catch ex As System.Exception
                        acDoc.Editor.WriteMessage(ex.Message & vbLf & ex.StackTrace)
                    End Try
                End Using
            End Using
    
            Return ReadVal
        End Function
    
        <CommandMethod("XXD")> _
        Public Sub Getdictionary()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor
            Dim db As Database = doc.Database
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim dn As String = "BM-LinkDictionary" ''<--- change dictionary name to your suit
                Dim dict As DBDictionary = GetDict(db, tr, dn)
                Dim msg As String = ""
                For Each de As DictionaryEntry In dict
                    msg = msg + de.Key.ToString + vbTab + de.Value.ToString + vbLf
                Next
                MsgBox(msg)
            End Using
        End Sub
    End Class
    ~'J'~

Page 2 of 2 FirstFirst 12

Similar Threads

  1. "Save As AutoCAD Drawing" - save to Object Data not just XDATA.
    By Wish List System in forum Civil 3D Wish List
    Replies: 4
    Last Post: 2015-02-12, 03:33 AM
  2. Getting subentity data from entity. . .
    By M. Kubitza in forum AutoLISP
    Replies: 4
    Last Post: 2009-06-06, 11:26 AM
  3. Replies: 0
    Last Post: 2009-04-15, 02:42 PM
  4. Object data from entity to FDO Feature data property
    By vlee in forum AutoCAD Map 3D - Data Connect (FDO)
    Replies: 3
    Last Post: 2009-04-09, 04:59 PM
  5. Save entity for later use
    By Coolmo in forum VBA/COM Interop
    Replies: 7
    Last Post: 2005-01-27, 07:34 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •