侧载DWG插入带属性块报wrong database错误,求解决思路
问题与解决方案
用户问题
我尝试用以下代码在侧载DWG中插入带属性的块时,在
brBlock.AttributeCollection.AppendAttribute(ar);行出现“wrong database”错误。我曾尝试从BlockReference中获取BlockTableRecord但未成功,能否有人指出我操作中的问题?提前感谢。
用户提供的代码
using (Database targetDb = new Database(false, true)) { using (Transaction tr = targetDb.TransactionManager.StartTransaction()) { targetDb.ReadDwgFile(file, FileOpenMode.OpenForReadAndAllShare, true, ""); targetDb.CloseInput(true); bool bFixErrors = true; bool becho = true; ImportAlstomFiles.TransformDwg.InsertTbmBlock(targetDb); targetDb.Audit(bFixErrors, becho); targetDb.SaveAs(file, DwgVersion.Current); tr.Commit(); } } public class TransformDwg { public static void InsertTbm(Database db) { string[] files = Directory.GetFiles(@"C:\ProgramData\Autodesk\ApplicationPlugins\SpNwDo.bundle\Contents\Block\Alstom\", "*.dwg"); foreach (string file in files) { string blockname = Path.GetFileNameWithoutExtension(file); using (Transaction tr = db.TransactionManager.StartTransaction()) { Database tmpDb = new Database(false, true); tmpDb.ReadDwgFile(file, FileShare.Read, true, ""); db.Insert(blockname, tmpDb, true); tr.Commit(); } } Point3d insPoint = new Point3d(); using (Transaction tr = db.TransactionManager.StartTransaction()) { // Open BlockTable and BlockTableRecord BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // Retrieve the inserted block definition BlockTableRecord btrBlock = tr.GetObject(bt["Alstom_TBM_DATA01_S_N"], OpenMode.ForRead) as BlockTableRecord; // Loop through the inserted block references and retrieve attribute values foreach (ObjectId btrId in btr) { if (btrId.ObjectClass.DxfName == "INSERT") { BlockReference br = tr.GetObject(btrId, OpenMode.ForWrite) as BlockReference; SymbolTableRecord str = tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead) as SymbolTableRecord; using (BlockReference brBlock = new BlockReference(insPoint, btrBlock.ObjectId)) { btr.UpgradeOpen(); // Append the new BlockReference to PaperSpace btr.AppendEntity(brBlock); tr.AddNewlyCreatedDBObject(brBlock, true); // Loop through BlockTableRecord to create AttributeReferences foreach (ObjectId btrBlockId in btrBlock) { AttributeDefinition ad = tr.GetObject(btrBlockId, OpenMode.ForWrite) as AttributeDefinition; if (ad != null) { // Create a new AttributeReference in the correct database (db) using (AttributeReference ar = new AttributeReference()) { // Set the attribute values and transformation ar.SetAttributeFromBlock(ad, brBlock.BlockTransform); // Update the text for each attribute based on collected values if (ar.Tag == "AT_DATA_ZONE_N") ar.TextString = zone; if (ar.Tag == "AT_DATA_STATION_N") ar.TextString = station; if (ar.Tag == "AT_DATA_BLOCKNUM_N") ar.TextString = blocknum; if (ar.Tag == "AT_DATA_DESC3_S_N") ar.TextString = lijn1; if (ar.Tag == "AT_DATA_DESC4_S_N") ar.TextString = lijn2; if (ar.Tag == "AT_DATA_DESC5_S_N") ar.TextString = lijn3; // Add the AttributeReference to the BlockReference's AttributeCollection brBlock.AttributeCollection.AppendAttribute(ar); // Ensure the attribute is added to the transaction tr.AddNewlyCreatedDBObject(ar, true); } } } } } } } } } }
问题分析与修正
核心错误原因
wrong database错误是因为**AttributeReference对象的数据库上下文与BlockReference(brBlock)不匹配**:你用无参构造函数创建AttributeReference时,它默认不属于目标数据库db,而brBlock是属于db的,两者数据库不一致导致附加属性时报错。
具体问题及修复
为
AttributeReference指定目标数据库
创建AttributeReference时,必须明确关联到目标数据库db,可以通过重载构造函数实现:using (AttributeReference ar = new AttributeReference(db))或者在创建后设置
ar.Database = db;,确保属性对象和块引用属于同一个数据库。修改
AttributeDefinition的打开模式
遍历块定义中的属性定义时,仅需读取信息,无需以写模式打开,改成OpenMode.ForRead即可:AttributeDefinition ad = tr.GetObject(btrBlockId, OpenMode.ForRead) as AttributeDefinition;移除冗余的
UpgradeOpen调用
已经将模型空间btr以OpenMode.ForWrite打开,循环内无需重复调用btr.UpgradeOpen();,可以删除该语句。
修正后的关键代码片段
// 遍历块定义中的属性定义 foreach (ObjectId btrBlockId in btrBlock) { AttributeDefinition ad = tr.GetObject(btrBlockId, OpenMode.ForRead) as AttributeDefinition; if (ad != null) { // 创建AttributeReference时指定目标数据库 using (AttributeReference ar = new AttributeReference(db)) { ar.SetAttributeFromBlock(ad, brBlock.BlockTransform); // 设置属性文本 if (ar.Tag == "AT_DATA_ZONE_N") ar.TextString = zone; if (ar.Tag == "AT_DATA_STATION_N") ar.TextString = station; if (ar.Tag == "AT_DATA_BLOCKNUM_N") ar.TextString = blocknum; if (ar.Tag == "AT_DATA_DESC3_S_N") ar.TextString = lijn1; if (ar.Tag == "AT_DATA_DESC4_S_N") ar.TextString = lijn2; if (ar.Tag == "AT_DATA_DESC5_S_N") ar.TextString = lijn3; brBlock.AttributeCollection.AppendAttribute(ar); tr.AddNewlyCreatedDBObject(ar, true); } } }
其他潜在问题
- 代码中
zone、station等变量未定义,需确保这些变量已正确赋值。 - 插入块的循环中,每次创建独立事务并提交可以优化为单个事务处理所有块插入,提升性能。
内容的提问来源于stack exchange,提问作者Pluribus
相关产品推荐
相关产品推荐

