بنقرة واحدة
acad-database-operations
Database cloning, DeepClone, WblockClone, IdMapping, side databases, Purge, Audit
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Database cloning, DeepClone, WblockClone, IdMapping, side databases, Purge, Audit
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Corridors, baselines, regions, assemblies, subassemblies, corridor surfaces
Custom subassembly .NET design — CorridorState, SubassemblyGenerator, targets, SATemplate
Stock-subassembly pattern catalog — need→file index, worked DrawImplement recipes, point/link/shape code reference, mined from Autodesk's 120 VB stock subassemblies
Superelevation design, attainment, cross slope, pivot points, lane config
Block definitions, references, attributes, dynamic block properties, exploding
Dimensions — aligned, rotated, arc, radial, angular, ordinate, text overrides
| name | acad-database-operations |
| description | Database cloning, DeepClone, WblockClone, IdMapping, side databases, Purge, Audit |
Use this skill when copying objects between databases, processing external .dwg files, importing blocks, purging unused records, or working with side databases outside the active document.
WblockCloneObjects copies objects from one database to another. This is the primary mechanism for importing entities, symbol table records, or any named objects across drawings.
public static void CopyEntitiesBetweenDatabases(
Database sourceDb, Database destDb, ObjectIdCollection sourceIds)
{
using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
{
ObjectId destModelSpaceId = SymbolUtilityServices.GetBlockModelSpaceId(destDb);
IdMapping idMap = new IdMapping();
sourceDb.WblockCloneObjects(
sourceIds, // objects to copy
destModelSpaceId, // owner in destination database
idMap, // receives old-to-new ObjectId mapping
DuplicateRecordCloning.Ignore, // how to handle name collisions
false); // deferTranslation -- false for immediate resolution
tr.Commit();
}
}
For symbol table records (layers, text styles, etc.), the destination owner is the corresponding symbol table in the target database.
public static void CopyLayersBetweenDatabases(Database sourceDb, Database destDb)
{
using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
{
LayerTable srcLt = (LayerTable)tr.GetObject(sourceDb.LayerTableId, OpenMode.ForRead);
ObjectIdCollection layerIds = new ObjectIdCollection();
foreach (ObjectId layerId in srcLt)
{
LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForRead);
if (ltr.Name != "0")
layerIds.Add(layerId);
}
IdMapping idMap = new IdMapping();
sourceDb.WblockCloneObjects(
layerIds, destDb.LayerTableId, idMap,
DuplicateRecordCloning.Ignore, false);
tr.Commit();
}
}
DeepCloneObjects copies objects within a single database. It cannot cross database boundaries.
public static ObjectIdCollection DuplicateEntities(
Database db, ObjectIdCollection sourceIds, ObjectId ownerId)
{
IdMapping idMap = new IdMapping();
db.DeepCloneObjects(sourceIds, ownerId, idMap, false);
ObjectIdCollection newIds = new ObjectIdCollection();
foreach (IdPair pair in idMap)
{
if (pair.IsCloned && pair.IsPrimary)
newIds.Add(pair.Value);
}
return newIds;
}
The destination owner can be any container -- model space, paper space, or a BlockTableRecord for cloning entities into a block definition.
Controls how name collisions are resolved when cloning named objects (layers, block definitions, text styles, etc.).
| Value | Behavior |
|---|---|
NotApplicable | No duplicate handling (used for unnamed objects) |
Ignore | Keep the existing destination record; skip the source record |
Replace | Overwrite the destination record with the source record |
XrefMangleName | Rename using xref-style convention (BlockName$0$SymbolName) |
MangleName | Rename with a numeric suffix to avoid collision (SymbolName_1) |
Ignore is the safe default for imports. Replace forces source definitions onto the destination. XrefMangleName preserves both, matching bind-style naming.
IdMapping tracks the correspondence between source and destination ObjectIds after a clone operation.
public static ObjectId TranslateId(IdMapping idMap, ObjectId sourceId)
{
if (idMap.Contains(sourceId))
{
IdPair pair = idMap[sourceId];
if (pair.IsCloned)
return pair.Value;
}
return ObjectId.Null;
}
// Iterate all mapped pairs
foreach (IdPair pair in idMap)
{
ObjectId sourceId = pair.Key; // original ObjectId
ObjectId destId = pair.Value; // new ObjectId in destination
bool cloned = pair.IsCloned; // true if actually cloned
bool primary = pair.IsPrimary; // true if top-level requested object
bool owner = pair.IsOwnerXlated; // true if owner was translated
}
ObjectIds are database-specific -- an ObjectId from one database is meaningless in another. Always use IdMapping from clone operations to translate between databases.
Insert reads an entire .dwg file and creates a block definition from it.
public static ObjectId InsertDrawingAsBlock(
Database db, string dwgPath, string blockName)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
ObjectId blockId = db.Insert(
blockName, // name for the new block definition
dwgPath, // path to the .dwg file
false); // preserveSourceDatabase -- false to allow cleanup
BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);
BlockReference blockRef = new BlockReference(Point3d.Origin, blockId);
modelSpace.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
tr.Commit();
return blockId;
}
}
To merge file content directly, insert as a block reference then call ExplodeToOwnerSpace() and erase the reference.
Wblock exports objects or the entire database to a new .dwg file.
// Wblock selected objects
using (Database newDb = db.Wblock(objectIds, Point3d.Origin))
newDb.SaveAs(outputPath, DwgVersion.Current);
// Wblock entire database (clean copy, strips unused objects)
using (Database newDb = db.Wblock())
newDb.SaveAs(outputPath, DwgVersion.Current);
// Wblock a single block definition (contents become model space)
using (Database newDb = db.Wblock(blockDefId))
newDb.SaveAs(outputPath, DwgVersion.Current);
public static void ProcessExternalDrawing(string dwgPath)
{
using (Database sideDb = new Database(false, true))
{
sideDb.ReadDwgFile(dwgPath, FileOpenMode.OpenForReadAndAllShare, true, null);
// Parameters: path, fileMode, allowCPConversion, password
using (Transaction tr = sideDb.TransactionManager.StartTransaction())
{
BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(
SymbolUtilityServices.GetBlockModelSpaceId(sideDb), OpenMode.ForRead);
foreach (ObjectId entId in modelSpace)
{
Entity ent = (Entity)tr.GetObject(entId, OpenMode.ForRead);
// Process entity...
}
tr.Commit();
}
}
}
DwgVersion.Current -- same version as the running AutoCADDwgVersion.AC1032 -- AutoCAD 2018-2025 formatDwgVersion.AC1027 -- AutoCAD 2013-2017 formatDwgVersion.AC1024 -- AutoCAD 2010-2012 formatCall sideDb.CloseInput(true) after ReadDwgFile to release the file lock while keeping the database usable in memory.
A "side database" is a Database created independently of any open document -- essential for batch processing, file inspection, or migrating objects without opening the drawing in the editor.
public static void BatchImportBlocks(string[] dwgPaths, Database activeDb)
{
foreach (string path in dwgPaths)
{
using (Database sideDb = new Database(false, true))
{
sideDb.ReadDwgFile(path, FileOpenMode.OpenForReadAndAllShare, true, null);
using (Transaction tr = sideDb.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(sideDb.BlockTableId, OpenMode.ForRead);
ObjectIdCollection blockIds = new ObjectIdCollection();
foreach (ObjectId btrId in bt)
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(
btrId, OpenMode.ForRead);
if (!btr.IsLayout && !btr.IsAnonymous && !btr.IsFromExternalReference)
blockIds.Add(btrId);
}
if (blockIds.Count > 0)
{
IdMapping idMap = new IdMapping();
sideDb.WblockCloneObjects(
blockIds, activeDb.BlockTableId, idMap,
DuplicateRecordCloning.Ignore, false);
}
tr.Commit();
}
}
}
}
// new Database(bool buildDefaultDrawing, bool noDocument)
new Database(false, true) // empty shell for ReadDwgFile
new Database(true, true) // new drawing from scratch (Layer 0, model space, etc.)
Purge filters an ObjectIdCollection in-place, removing IDs that are still referenced. The remaining IDs are safe to erase.
public static void PurgeUnusedLayers(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
ObjectIdCollection layerIds = new ObjectIdCollection();
foreach (ObjectId id in lt)
layerIds.Add(id);
db.Purge(layerIds); // filters in-place
foreach (ObjectId id in layerIds)
{
SymbolTableRecord record = (SymbolTableRecord)tr.GetObject(id, OpenMode.ForWrite);
record.Erase();
}
tr.Commit();
}
}
For a full purge, loop over all symbol tables (BlockTableId, LayerTableId, LinetypeTableId, TextStyleTableId, DimStyleTableId, RegAppTableId) and repeat until nothing more can be purged -- removing one record may make others purgeable.
// fix: true = attempt repair, false = report only
// logToFile: true = create .adt audit log
db.Audit(true, false);
For side databases, always save to a new file after auditing to preserve the original.
The WorkingDatabase property determines which database receives new objects when code does not explicitly specify a target. Critical when working with side databases -- symbol name resolution (e.g., layer "0") uses WorkingDatabase, not the transaction's database.
Database previousDb = HostApplicationServices.WorkingDatabase;
try
{
HostApplicationServices.WorkingDatabase = sideDb;
using (Transaction tr = sideDb.TransactionManager.StartTransaction())
{
// Operations now resolve against sideDb
tr.Commit();
}
}
finally
{
HostApplicationServices.WorkingDatabase = previousDb;
}
WblockCloneObjects requires the source transaction to be open during the call. If the transaction commits or aborts before cloning, the ObjectIds become invalid.DeepCloneObjects cannot cross database boundaries -- use WblockCloneObjects for inter-database copies.deferTranslation parameter (last bool on clone methods) should almost always be false. Setting it to true defers ObjectId resolution and requires manual TranslateIdsToOwnerSpace().Wblock() with no arguments creates a clean copy, stripping unused objects. Equivalent to WBLOCK * in the UI.new Database(false, true) creates an empty shell -- do NOT start transactions before calling ReadDwgFile.new Database(true, true) creates a valid default drawing. Use this when building a new .dwg from scratch.Purge() modifies the input collection in-place. Run in a loop because removing one record may make others purgeable.Audit(true, false) can modify the database silently. Save to a new file to preserve the original.WorkingDatabase after switching will cause the active document to malfunction. Always use try/finally.ReadDwgFile with FileOpenMode.OpenForReadAndAllShare is the safest mode for batch processing.IdMapping iteration includes both primary and dependency entries. Filter on IdPair.IsPrimary to process only requested objects.WblockCloneObjects automatically clones dependent objects (layers, linetypes, text styles). You do not need to clone symbol table records separately when copying entities.DuplicateRecordCloning.Replace overwrites the destination record entirely, which can change the appearance of existing entities that reference it.acad-xrefs -- xref binding uses clone operations internally; BindXrefs is a specialized form of WblockCloneObjectsacad-blocks -- block import across drawings uses Insert or WblockCloneObjects with block table as destinationacad-xdata-dictionaries -- xdata and extension dictionary entries travel with cloned objects; dictionary cloning requires explicit handlingacad-layers -- layer records are symbol table entries that follow DuplicateRecordCloning rules during cross-database cloning