Does adding XData always overwrite the existing data?

Does adding XData always overwrite the existing data?

nshupeFMPE3
Advocate Advocate
738 Views
3 Replies
Message 1 of 4

Does adding XData always overwrite the existing data?

nshupeFMPE3
Advocate
Advocate

I use to utilize Xdata fairly extensively in our code base, until we started getting Audit errors

XData Handle Unknown


which motivated me to start using ExtensionDictionaries. I want to try and start bringing XData back as a tool I can use. But I had a question around setting XData which was motivated by my seeing this method

DBObject.GetXDataForApplication

If Xdata can be retrieved from an object based on the Application RegAppTable entry, then that means multiple Applications XData can exist on the same object. I've seen AutoCAD add xdata to objects before. 

The methods that I use to use would always store things as a string. And I would append a unique application string to the beginning of that data so that I could differentiate my apps entries in the XData vs other applications. So anything that didnt have that unique application string I would copy into the new ResultBuffer, and then I would add the data I wanted to add to the end of the ResultBuffer. 

I wonder if this was even neccessary or might have caused some of my problems by adding unneeded complexity. When I add XData by doing something like 

DbObject.XData = new ResultBuffer(....);


 am I removing any existing data that might have been there, or does the API keep track of different Appplications XData?

Here is some code I wrote just to show the simpliest way to add Xdata and Extension Dictionary data

[CommandMethod(nameof(XDataVsExtensionDictionary))]
public void XDataVsExtensionDictionary()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;

    string appName = "MyAppName";

    var result = ed.GetEntity($"\nSelect polyline:");

    if (result.Status != PromptStatus.OK) return;

    ObjectId plineId = result.ObjectId;

    using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
    {
        try
        {
            var regAppTableId = db.RegAppTableId;

            using (RegAppTable appTable =
                   tr.GetObject(regAppTableId, OpenMode.ForRead, false, true) as RegAppTable)
            {
                if (!appTable.Has(appName))
                {
                    SymbolTableRecord newEntry = new RegAppTableRecord();
                    newEntry.Name = appName;

                    appTable.UpgradeOpen();

                    appTable.Add(newEntry);
                    tr.AddNewlyCreatedDBObject(newEntry, true);
                }
            }
            
            
            using (Polyline line = tr.GetObject(plineId, OpenMode.ForWrite, false, true) as Polyline)
            {
                //xdata method
                var data = new ResultBuffer(new[]
                {
                    new TypedValue((short)DxfCode.ExtendedDataRegAppName, appName),
                    new TypedValue((short)DxfCode.ExtendedDataAsciiString, "Some Data")
                });

                line.XData = data;

                //Extension Dictionary

                if (line.ExtensionDictionary == ObjectId.Null)
                {
                    line.CreateExtensionDictionary();
                }

                using (DBDictionary extensionDictionary =
                       tr.GetObject(line.ExtensionDictionary, OpenMode.ForWrite, false, true) as DBDictionary)
                {
                    var extendData = new ResultBuffer(new[]
                    {
                        new TypedValue((short)DxfCode.Text, "Some Extended Data")
                    });

                    Xrecord record = new Xrecord();
                    record.Data = extendData;

                    ObjectId recordId = extensionDictionary.SetAt("SomeKey", record);

                    tr.AddNewlyCreatedDBObject(record, true);
                }

            }

            tr.Commit();
        }
        catch
        {
            tr.Abort();
            return;
        }
    }
}
0 Likes
Accepted solutions (2)
739 Views
3 Replies
Replies (3)
Message 2 of 4

ActivistInvestor
Mentor
Mentor
Accepted solution

You can register any number of registered application ids for XData, there is no limit on how many you can have. The fact that they are called "Application ids" or "AppIds" doesn't mean that a single app can't register and use multiple "app ids". Many apps use multiple APPIDs to distinguish xdata by its purpose or meaning rather than by the application that manages it.

 

You can think of xdata as a dictionary where the AppIds are keys, and resultbuffers are values.

 

You use the registered application as a "key" when you assign XData using the XData property of DBObject. Whatever xdata was previously stored with the application id is replaced. XData for other registered applications is not altered, only the xdata for the appid that the xdata list starts with. You can also set Xdata for multiple appids in a single assignment to the XData property, by adding their appids at the start of their Xdata, but I don't recommend doing that because it can become confusing.

 

0 Likes
Message 3 of 4

nshupeFMPE3
Advocate
Advocate

So if I understand you correctly if I had an Object with some XData for ApplicationA (maybe thats Autocad its self for instance)

//sudo code, not real

DBObject.Xdata
{
    TypedValue{ (short)DxfCode.ExtendedDataRegAppName, "ApplicationA"},
    TypedValue{ (short)DxfCode.ExtendedDataAsciiString, "SomeOtherAppsData"}
}


and then I make my own ResultBuffer and do 

DbObject.XData = myResultBuffer



that the existing xdata is not lost. In which case I dont have to worry about preserving other apps XData when adding my own?

Also I had never throught of using multiple ApplicationId's for XData that is brilliant though

0 Likes
Message 4 of 4

ActivistInvestor
Mentor
Mentor
Accepted solution

The XData for the applications whose appids you include in the resultbuffer are replaced (or deleted if there is nothing following the appid). XData associated with appids that aren't included in the resultbuffer is not replaced or removed.

0 Likes