Side loading database won't populate CivilApplication.ActiveDocument?

Side loading database won't populate CivilApplication.ActiveDocument?

soonhui
Advisor Advisor
922 Views
9 Replies
Message 1 of 10

Side loading database won't populate CivilApplication.ActiveDocument?

soonhui
Advisor
Advisor

Motivation:

I need to side load the AutoCAD database as per below, because otherwise I won't be able to run the unit tests. I wrote the below code modelling after @CADbloke 's excellent code

 

Problem statement:

 

For some reason, if I side load the AutoCAD database, the CivilApplication.ActiveDocument won't be populated accordingly. Here's the code:

 

 

 

       [CommandMethod(nameof(SideLoadingDatabase))]
        public void SideLoadingDatabase()
        {
            Document doc =  Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
            using (doc.LockDocument())
            {

                using (var db = new Database(false, false))
                {
                    var drawingPath = @"D:\.net Samples project\September 2022\AcadTestBug\AcadTestBug\Drawing1.dwg";
                    db.ReadDwgFile(drawingPath, FileOpenMode.OpenForReadAndWriteNoShare, true, null);

                    using (new WorkingDatabaseSwitcher(db))
                    {
                        using (var ts = db.TransactionManager.StartTransaction())
                        {
                            var sourceBlockTable = ts.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                            var sourceModelSpace =
                                ts.GetObject(sourceBlockTable[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;

                            var civilDoc =CivilDocument.GetCivilDocument(db); //this still doesn't change anything
                            var objectIdCollection = civilDoc.GetSurfaceIds();  //this is 0 count even though the DWG does contain surface

                            var allNetwork = civilDoc.GetPipeNetworkIds(); //this is 0 count even though the DWG does contain Pipe networks
                            foreach (var objeId in sourceModelSpace)
                            {
                                var tinSurface = ts.GetObject(objeId, OpenMode.ForWrite) as TinSurface;
                                if (tinSurface != null)
                                {
                                   // Yes, TinSurface exists ! And so does Pipe Network!!
                                }
                            }
                            ts.Commit();
                        }                     
                    }

                }
            }
        }

 

 

 

 

 

 

 

    public sealed class WorkingDatabaseSwitcher : IDisposable
    {
        Database _oldDb = null;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="db">Target database.</param>
        public WorkingDatabaseSwitcher(Database db)
        {
            _oldDb = HostApplicationServices.WorkingDatabase;
            HostApplicationServices.WorkingDatabase = db;
        }

        public void Dispose()
        {
            HostApplicationServices.WorkingDatabase = _oldDb;
        }
    }

 

 

 

No such problem if I just open the DWG drawing in the Civil 3D and then run the above command line.

 

As mentioned in the code, even though Civil objects like TinSurface and PipeNetwork exist in the drawing, but civilDoc.GetSurfaceIds() and civilDoc.GetPipeNetworkIds() return 0 count. 

 

How can I get CivilApplication.Document working correctly if I have to sideload the database?

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Accepted solutions (1)
923 Views
9 Replies
Replies (9)
Message 2 of 10

soonhui
Advisor
Advisor

Opps, I think this should be moved to the Civil 3D customization forum...

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 3 of 10

Jeff_M
Consultant
Consultant

This:

var civilDoc = CivilApplication.ActiveDocument;

I believe is still using the original active document. Use this instead:

var civilDoc = CivilDocument.GetCivilDocument(db);

 

Jeff_M, also a frequent Swamper
EESignature
Message 4 of 10

soonhui
Advisor
Advisor

@Jeff_M , no , it doesn't work because

 

var civilDoc = CivilApplication.ActiveDocument;

 

and 

var civilDoc = CivilDocument.GetCivilDocument(db);

 

Are one and the same. You get Compute the HashCode for both and you will find that both are equivalent. 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 5 of 10

norman.yuan
Mentor
Mentor

@soonhui : you are wrong and @Jeff is correct (as always!). Since you open the drawing as side database, the equivalent in C3D's "side C3D document" should be created by using the static method CivilDocument.GetCivilDocument(database), not from CivilApplication.ActiveDocument. It is very straightforward logically: side database is not ActiveDocument's database.

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 6 of 10

Jeff_M
Consultant
Consultant

@norman.yuan @soonhui I use a side database in a number of tools and always use the CivilDocument.GetCivilDocument(db). However, in testing the above code I've found some strange things occurring. If I merely comment out the using database switcher the code runs fine and the surface & network ids are returned for the drawing I started the command in.

 

When I change the var civilDoc line as I suggested, then they both return 0 objectIds. If I check any of the Styles, these are showing the correct number of styles in the side database. So not sure why the Get*Ids fail with a side database.

 

 

 

Jeff_M, also a frequent Swamper
EESignature
0 Likes
Message 7 of 10

norman.yuan
Mentor
Mentor

Well, in my resent ongoing development with C3D, I use side database and obtain a CivilDocument with the static method GetCivilDocument(database) a lot, because the business process requirements. I always get needed C3D information from the side/in memory CivilDocument. Never expected/tried to load drawing as side database and then access the C3D data in the side database via CivilApplication.ActiveDocument, it just feels illogical, to me. 

Norman Yuan

Drive CAD With Code

EESignature

0 Likes
Message 8 of 10

soonhui
Advisor
Advisor

@norman.yuan , OK, now I retested and you are right. They are different.

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 9 of 10

soonhui
Advisor
Advisor

@Jeff_M , 

 

Can you post your code? Because I can't reproduce your behavior with my following code:

 

 

 

 

            Document doc =  Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
            using (doc.LockDocument())
            {

                using (var db = new Database(false, false))
                {
                    var drawingPath = @"D:\.net Samples project\September 2022\AcadTestBug\AcadTestBug\Drawing1.dwg";
                    db.ReadDwgFile(drawingPath, FileOpenMode.OpenForReadAndWriteNoShare, true, null);
                    var civilDoc = CivilDocument.GetCivilDocument(db);
               
                    var objectIdCollection = civilDoc.GetSurfaceIds().Count;  //this is 0 count even though the DWG does contain surface

                    var allNetwork = civilDoc.GetPipeNetworkIds().Count; //this is 0 count even though the DWG does contain Pipe networks

                }
            }

 

 

 

 

It's always 0 when I get from Civil Document-- regardless of whether it's side database or the active database. 

 

The behavior you and I observe are both not right; they all look like bugs to me. 

 

Note:

However, in my main, as-it-is test code, for the same drawing, GetSurfaceIds() count returns 0 ( incorrectly) while GetPipeNetworkIds() count returns 2 ( correctly). 

##########

Ngu Soon Hui

##########

I'm the Benevolent Dictator for Life for MiTS Software. Read more here


I also setup Civil WHIZ in order to share what I learnt about Civil 3D
0 Likes
Message 10 of 10

angelohbwang
Autodesk
Autodesk
Accepted solution

@soonhui Most likely, you will need to call CloseInput(true) after ReadDwgFile(), otherwise your drawing is not fully read into the memory. Alternatively, you can pass FileOpenMode.OpenForReadAndAllShare to ReadDwgFile(), where CloseInput() is implicitly called. See more details on the API reference page, https://help.autodesk.com/view/OARX/2023/ENU/?guid=OARX-ManagedRefGuide-Autodesk_AutoCAD_DatabaseSer...