setLayer for very large amount (600k+) of items in Civil3D DWG

Hello,

I am trying to build a script that corrects autocad files. Basically our clients expect lines, polylines, circles etc to be placed in layer “X”.

I thought id just grab all these elements like so:

And then just run all those items through a obj.setlayer node, but some drawings have more than half a million lines, which just freezes Dynamo indefinitely (i assume, stopped after waiting for half an hour) .

So then i tried to feed it into a python script, i thought id just grab the entire array and then run over it in batches so i dont fill the memory before comitting everything. But… Im getting an error in the basic version of the python script (that doesn’t deal with batching yet)

The code below gives the following error:
"No method matches given arguments for OnExit (<class 'Autodesk.Autocad.ApplicationServices.DocumentLock>, <class ‘type’>, <class ‘TypeError’>,<class ‘traceback’>)… line 40 (the line with t.commit()

# Load the Python Standard and DesignScript Libraries
import sys
import clr

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *

# The inputs to this node will be stored as a list in the IN variables.
objects = IN[0]  # List of objects
layer_name = IN[1]  # Layer name
changed_objects = []

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

with adoc.LockDocument():
    with adoc.Database as db:

        with db.TransactionManager.StartTransaction() as t:
            for obj in objects:
                if isinstance(obj, Autodesk.AutoCAD.DatabaseServices.Entity):
                    obj.Layer = layer_name
                    changed_objects.append(obj)
            t.Commit()
            

# Assign your output to the OUT variable.
OUT = changed_objects
type or paste code here

Can someone help me out with the error, or tell me there’s a better/faster way to change a bagillion object layers?

Hi @Garbage_Collector

try to split the process into several transactions

# Load the Python Standard and DesignScript Libraries
import sys
import clr

# Add Assemblies for AutoCAD and Civil3D
clr.AddReference('AcMgd')
clr.AddReference('AcCoreMgd')
clr.AddReference('AcDbMgd')
clr.AddReference('AecBaseMgd')
clr.AddReference('AecPropDataMgd')
clr.AddReference('AeccDbMgd')

# Import references from AutoCAD
from Autodesk.AutoCAD.Runtime import *
from Autodesk.AutoCAD.ApplicationServices import *
from Autodesk.AutoCAD.EditorInput import *
from Autodesk.AutoCAD.DatabaseServices import *
from Autodesk.AutoCAD.Geometry import *

# Import references from Civil3D
from Autodesk.Civil.ApplicationServices import *
from Autodesk.Civil.DatabaseServices import *


# The inputs to this node will be stored as a list in the IN variables.
objects = IN[0]  # List of objects
layer_name = IN[1]  # Layer name
changed_objects = []

adoc = Application.DocumentManager.MdiActiveDocument
editor = adoc.Editor

# max elems by transaction 
n = 2000
chunk_lst = [objects[i:i+n] for i in range(0, len(objects), n)] 

with adoc.LockDocument():
    db = adoc.Database
    #
    for sub_objects in chunk_lst:
        t = db.TransactionManager.StartTransaction()
        for obj in sub_objects:
            ent = t.GetObject(obj.AcadObjectId, OpenMode.ForWrite)
            ent.Layer = layer_name
            changed_objects.append(obj)
        t.Commit()
        t.Dispose()
    db.Dispose()

# Assign your output to the OUT variable.

OUT = changed_objects