Error while transferring Object Data

Error while transferring Object Data

subash.nalla
Enthusiast Enthusiast
1,171 Views
10 Replies
Message 1 of 11

Error while transferring Object Data

subash.nalla
Enthusiast
Enthusiast

I have a MapInfo (.MIF) file, was able to successfully import into AutoCAD Map 3D 2015 using Autodesk.Gis.Map.ImportExport.Importer import = app.Application.Importer; along with Object Data. The features were imported as point features. I have to insert an attribute block for each point feature and need to transfer the Object Data and then need to update the Attribute data from Object Data and getting the following exception "Exception of type 'Autodesk.Gis.Map.MapException' was thrown". I have attached the class file and the exception log as an attachment and request for help. Please also let me know for any other information.

0 Likes
Accepted solutions (1)
1,172 Views
10 Replies
Replies (10)
Message 2 of 11

fieldguy
Advisor
Advisor

your post belongs in the Map Developer forum again. 

Can you provide test data? a dwg file with some points with object data and the block definition "NBN_TPT"?

my guess is the error is in "OdUtils.getFieldValue".  Set a breakpoint there and check the value of IList<string> data;  

0 Likes
Message 3 of 11

norman.yuan
Mentor
Mentor

The error logs in your attachment is useless without knowing which line of the code causes it. Have you actually step through your code in debugging to identify which line of code raises the exception? You really should post relevant code and point out the offending line so other can at least has a focus point to respond from; instead of place all the code in an attachment and let others to guess where things could go wrong (not to mention, downloading/opening attachment from an open forum/unknown source could be potentially harmful, many people may just ignore it).

 

With that said, I did "take an unknown risk" and quickly browsed your code in the class "OdUtils" and spotted bad code in the transferObjectData() method:

 

You do not need to start a Transaction to read OD data from an entity, nor to add OD data to an entity. AutoCAD Map does it for you: OdTables.GetObjectRecords()/odTable.AddRecord() both take entity's ObjectId as input, not an opened Entity. That is, the 2 methods open Transaction inside as needed.

 

Your code explicitly starts a Transaction, and worse, open the 2 entities (one for reading OD from , the other for writing OD to) for WRITE. I think this is the source of the error: because of these 2 entities have been opened for writing, the further odTable.AddRecord() call cannot write OD data to the target entity with its own transaction inside.

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 4 of 11

subash.nalla
Enthusiast
Enthusiast
Thank you for the reply and suggestions. I will attach the files as suggested. I have used this "OdUtils.getFieldValue" method in the same solution for other features (polylines and lines from .MIF File) and didn't get any issue. I am not aware how to move this post to Map Developer forum.
0 Likes
Message 5 of 11

subash.nalla
Enthusiast
Enthusiast

Hi Thank you for your valuable suggestions will definitely follow them.

  1. I have attached the error logs file as it got generated after the execution and thought it might help for analyzing.
  2. I have debugged a lot and the exception is not consistent sometimes the it is occurring in using (Records odRecords = odTables.GetObjectRecords(0, sourceObjId, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false)) line in transferObjectData method Sometimes in Records tblRecords = tbl.GetObjectTableRecords(0, dbObj, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, true); line in getFieldValue method.
  3. I will remove the start transaction in transferObjectData() method as suggested.
  4. The same method is working fine across the solution for other features.
0 Likes
Message 6 of 11

subash.nalla
Enthusiast
Enthusiast

I changed my method like this and still getting the exception, please suggest me where I am going wrong. I got the exception while doing .AddRecord() method.

 

public static void transferObjectData(ObjectId sourceObjId, ObjectId targetObjId)
{
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.GetDocument(db);
using (DocumentLock docLk = doc.LockDocument())
{
//using (Transaction actr = db.TransactionManager.StartTransaction())
//{
//Entity srcEnt = (Entity)actr.GetObject(sourceObjId, OpenMode.ForWrite);
//Entity trgEnt = (Entity)actr.GetObject(targetObjId, OpenMode.ForWrite);
MapApplication mapApp = HostMapApplicationServices.Application;
Tables odTables = mapApp.ActiveProject.ODTables;
if (odTables.TablesCount == 0)
{
//actr.Commit();
return;
}
try
{
//using (Records odRecords = odTables.GetObjectRecords(0, sourceObjId, Autodesk.Gis.Map.Constants.OpenMode.OpenForWrite, false))
using (Records odRecords = odTables.GetObjectRecords(0, sourceObjId, Autodesk.Gis.Map.Constants.OpenMode.OpenForRead, false))
{
if (odRecords.Count > 0)
{
foreach (Record odRecord in odRecords)
{
Autodesk.Gis.Map.ObjectData.Table odTable = odTables[odRecord.TableName];
odTable.AddRecord(odRecord, targetObjId);
//actr.Commit();
}
}
}
}
catch (Autodesk.Gis.Map.MapException ex)
{
MessageBox.Show(ex.Message.ToString(), "NBN Map Import", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
}
//}
}
}

0 Likes
Message 7 of 11

subash.nalla
Enthusiast
Enthusiast

Hi we can have a Google meet meeting to look into the issue if possible for you.

0 Likes
Message 8 of 11

norman.yuan
Mentor
Mentor

Well, I did not go through your code line by line, just a quick browsing. By the way, when posting code here, please use the "</>" button of the toolbar (above the message window while you are entering your message), so that the code is formatted read-friendly.

 

The other obvious error in your code is to add an existing OD record retrieved from source entity to another entity (target entity). You cannot do that. You need to create a NEW OD record, set its values with the values obtained from the source entity's record (note: values!, not record!).

 

Following are code samples to copy OD data from one entity to another. Note, this is an extension method. 

 

 

public static void CopyObjectDataFrom(this ObjectId entId, ObjectId sourceEntId, ProjectModel mapProj = null)
        {
            var dicData = sourceEntId.RetrieveObjectDataFromEntity(mapProj);
            if (dicData.Count == 0) return;

            Autodesk.Gis.Map.ObjectData.Tables tables = null;

            if (mapProj == null) mapProj = HostMapApplicationServices.Application.ActiveProject;
            tables = mapProj.ODTables;

            foreach (var item in dicData)
            {
                if (!mapProj.ODTables.IsTableDefined(item.Key)) continue;

                using (var table = mapProj.ODTables[item.Key])
                {
                    var fldDefs = table.FieldDefinitions;
                    using (var record = Record.Create())
                    {
                        table.InitRecord(record);

                        for (int i = 0; i < fldDefs.Count; i++)
                        {
                            string fldName = fldDefs[i].Name;
                            OdField odFld = FindOdField(item.Value, fldName);
                            if (odFld == null) continue;

                            MapValue mapVal = record[i];

                            switch (odFld.DataType)
                            {
                                case Map.Constants.DataType.Character:
                                    mapVal.Assign(odFld.FieldValue.ToString());
                                    break;
                                case Map.Constants.DataType.Integer:
                                    mapVal.Assign(Convert.ToInt32(odFld.FieldValue));
                                    break;
                                case Map.Constants.DataType.Real:
                                    mapVal.Assign(Convert.ToDouble(odFld.FieldValue));
                                    break;
                                case Map.Constants.DataType.Point:
                                    mapVal.Assign((Point3d)odFld.FieldValue);
                                    break;
                            }
                        }

                        table.AddRecord(record, entId);
                    }
                }
            }


            //if (tables != null) tables.Dispose();
            //if (mapProj != null) mapProj.Dispose();
        }

 

This is the method RetrieveObjectDataFromEntity() used in above code:

 

 

public static Dictionary<string, IEnumerable<OdField>> RetrieveObjectDataFromEntity(this ObjectId entId, ProjectModel mapProj = null)
        {
            var dic = new Dictionary<string, IEnumerable<OdField>>();

            if (mapProj == null) mapProj = HostMapApplicationServices.Application.GetProjectForDB(entId.Database);

                var tables = mapProj.ODTables;
                if (tables.TablesCount > 0)
                {
                    using (Records records = tables.GetObjectRecords(0, entId, Map.Constants.OpenMode.OpenForRead, true))
                    {
                        if (records.Count > 0)
                        {
                            string tName = "";

                            try
                            {
                                foreach (Record record in records)
                                {
                                    tName = record.TableName;
                                    if (!tables.IsTableDefined(tName)) continue;

                                    var table = tables[tName];
                                    var fields = GetOdRecordData(record, table);

                                    dic.Add(tName, fields);
                                }
                            }
                            catch (Map.MapException ex)
                            {
                                string err = ((Map.Constants.ErrorCode)ex.ErrorCode).ToString();
                                throw new ApplicationException(
                                    "Cannot reach object data record!");
                            }
                        }
                    }
                }

            return dic;
        }

 

 

Also, this is the class OdField used in above code:

public class OdField
    {
        public string FieldName { set; get; }
        public object FieldValue { set; get; }
        public Map.Constants.DataType DataType { set; get; }

        public string StringValue
        {
            get
            {
                string ret = "";
                if (FieldValue != null)
                {
                    switch (DataType)
                    {
                        case Map.Constants.DataType.Character:
                            ret = FieldValue.ToString();
                            break;
                        case Map.Constants.DataType.Integer:
                            ret = ((int)FieldValue).ToString();
                            break;
                        case Map.Constants.DataType.Real:
                            ret = ((double)FieldValue).ToString();
                            break;
                        case Map.Constants.DataType.Point:
                            ret = ((Point3d)FieldValue).ToString();
                            break;
                    }
                }

                return ret;
            }
        }
    }

 

HTH

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 9 of 11

subash.nalla
Enthusiast
Enthusiast

Hi I think FindOdField and GetOdRecordData methods are missing in the code.

0 Likes
Message 10 of 11

norman.yuan
Mentor
Mentor
Accepted solution

OK, here they are:

 

private static List<OdField> GetOdRecordData(Record record, Map.ObjectData.Table table)
        {
            var lst = new List<OdField>();

            for (int i = 0; i < record.Count; i++)
            {
                FieldDefinition fld = table.FieldDefinitions[i];
                string fldName = fld.Name;

                object fldVal;
                var val = record[i];
                switch (fld.Type)
                {
                    case Map.Constants.DataType.Character:
                        fldVal = val.StrValue;
                        break;
                    case Map.Constants.DataType.Integer:
                        fldVal = val.Int32Value;
                        break;
                    case Map.Constants.DataType.Real:
                        fldVal = val.DoubleValue;
                        break;
                    case Map.Constants.DataType.Point:
                        fldVal = val.Point;
                        break;
                    default:
                        fldVal = "";
                        break;
                }

                lst.Add(new OdField()
                {
                    FieldName = fldName,
                    FieldValue = fldVal,
                    DataType=fld.Type
                });
            }

            return lst;
        }

        private static OdField FindOdField(IEnumerable<OdField> flds, string fieldName)
        {
            foreach (var fld in flds)
            {
                if (fld.FieldName.ToUpper() == fieldName.ToUpper()) return fld;
            }
            return null;
        }

        private static List<Tuple<string, MapValue>> GetSourceDataFromRecord(Record record, Autodesk.Gis.Map.ObjectData.Table sourceTable)
        {
            var lst = new List<Tuple<string, MapValue>>();

            for (int i=0; i<record.Count; i++)
            {
                var fld = sourceTable.FieldDefinitions[i];
                lst.Add(new Tuple<string, MapValue>(fld.Name, record[i]));
            }

            return lst;
        }

 

 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 11 of 11

subash.nalla
Enthusiast
Enthusiast

Hi thank you for the help the code solved my issue.

0 Likes