You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迭代添加多表记录问题:AutoCAD点转圆二次开发报错

AutoCAD二次开发:点转圆的问题解决

问题分析

你编写的点转圆程序遇到两个核心问题:

  1. 迭代创建圆时,调用AppendEntity生成第一个圆后抛出eAlreadyInDb异常
  2. 当前使用两个事务分别读取点和创建圆,不确定是否为最优方案

异常原因

你在循环外仅创建了一个Circle对象实例,第一次调用AppendEntity后,该对象已被添加到AutoCAD数据库中。第二次循环时再尝试将同一个对象添加到数据库,就会触发eAlreadyInDb异常——每个DBObject实例只能被添加到数据库一次。

事务效率问题

使用两个事务并非最高效方案。事务的开启、提交都有性能开销,读取点和创建圆的操作可以在同一个事务内完成,避免重复的事务管理开销。

修复后的代码

using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

[CommandMethod("PointsToCircles")]
public void PointsToCircles()
{
    Document adoc = Application.DocumentManager.MdiActiveDocument;
    Database adb = adoc.Database;
    Editor acDocEd = adoc.Editor;
    List<Point3d> vlist = new List<Point3d>();

    // 合并为单个事务,同时处理读取点和创建圆
    using (Transaction trans = adb.TransactionManager.StartTransaction())
    {
        // 读取块表
        BlockTable acBlkTbl = trans.GetObject(adb.BlockTableId, OpenMode.ForRead) as BlockTable;
        
        // 选择点对象的过滤器
        TypedValue[] acTypValAr = new TypedValue[1];
        acTypValAr.SetValue(new TypedValue((int)DxfCode.Start, "POINT"), 0);
        SelectionFilter acSelFtr = new SelectionFilter(acTypValAr);
        PromptSelectionResult acSSPrompt = acDocEd.GetSelection(acSelFtr);

        if (acSSPrompt.Status == PromptStatus.OK)
        {
            SelectionSet acSSet = acSSPrompt.Value;
            Application.ShowAlertDialog("选中的POINT数量: " + acSSet.Count.ToString());
            
            // 收集选中点的坐标
            foreach (SelectedObject acSSObj in acSSet)
            {
                if (acSSObj != null)
                {
                    DBPoint acDBP = trans.GetObject(acSSObj.ObjectId, OpenMode.ForRead) as DBPoint;
                    vlist.Add(acDBP.Position);
                }
            }

            // 打开模型空间用于写入
            BlockTableRecord acBlkTblRec = trans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
            
            // 循环创建圆:每次循环实例化新的Circle对象
            foreach (Point3d centerPoint in vlist)
            {
                Circle acCirc = new Circle();
                acCirc.Center = centerPoint;
                acCirc.Radius = 12.00;
                acBlkTblRec.AppendEntity(acCirc);
                trans.AddNewlyCreatedDBObject(acCirc, true);
            }
        }
        else
        {
            Application.ShowAlertDialog("选中的POINT数量: 0");
        }
        
        // 提交事务
        trans.Commit();
    }
}

关键修改点

  • 解决eAlreadyInDb异常:将Circle acCirc = new Circle();移到循环内部,每次迭代创建一个新的Circle实例,确保每个圆对象都是独立的,仅被添加到数据库一次。
  • 优化事务效率:将读取点和创建圆的逻辑合并到同一个事务中,减少事务开启/提交的开销,提升程序运行效率。
  • 简化代码:使用foreach遍历点列表,代码更简洁易读。

内容的提问来源于stack exchange,提问作者dengebre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:03:24