Autodesk.AutoCAD.Runtime.Exception:“eAlreadyInDb” happened at code “blockTableRecord.AppendEntity(entity);”

Autodesk.AutoCAD.Runtime.Exception:“eAlreadyInDb” happened at code “blockTableRecord.AppendEntity(entity);”

1755384511
Participant Participant
712 Views
2 Replies
Message 1 of 3

Autodesk.AutoCAD.Runtime.Exception:“eAlreadyInDb” happened at code “blockTableRecord.AppendEntity(entity);”

1755384511
Participant
Participant

I  want to create  a block from some selected entities,

here is the code :

MAIN FUNCTION: 

public class _ExtensionTest_{ 

 [CommandMethod(nameof(BlockCreateTEST023))]
  public void BlockCreateTEST023()
  {
      //AddEntityByDB aedb = new AddEntityByDB();
      Database database = HostApplicationServices.WorkingDatabase;
      Document document = Application.DocumentManager.MdiActiveDocument;
      Editor editor = document.Editor;
      String blockName = "BLOCK0001"; 

      var ccIds = document.SelectEntity().GetObjectIds() ;
      editor.WriteMessage($"{string.Join("+\n", ccIds)}  \n"); 
      var resID = ccIds.ToBlockTable(blockName);
      editor.WriteMessage($"resID:{resID}  ");
  }
}

 

HELPER CODE:

public  static class BlockExtension
{ 
  public static SelectionSet SelectEntity(this Document document, SelectionFilter selectionFilter = null)
  {
      Editor editor = document.Editor;
      //----------- 
      PromptSelectionResult promptSelRes = editor.SelectImplied(); 
      ObjectId[] emptyObjectId = new ObjectId[0];
      editor.SetImpliedSelection(emptyObjectId); 
      if (promptSelRes.Status != PromptStatus.OK)
      {
          if (selectionFilter == null)
          {
              promptSelRes = editor.GetSelection();
          }
          else
          {
              promptSelRes = editor.GetSelection(selectionFilter);
          }
      }

      SelectionSet selectionSet = null;

      if (promptSelRes.Status == PromptStatus.OK)
      {
          selectionSet = promptSelRes.Value;

          editor.WriteMessage($"selected num :{selectionSet.Count.ToString()}");
      }
      else
      {
          editor.WriteMessage($"selected num :0");
      }
      return selectionSet;
  }
         
}

public  static class ObjectExtension
{

 public static ObjectId ToBlockTable(this IEnumerable<ObjectId> objectIds, string blockName)
 {
     var database =  HostApplicationServices.WorkingDatabase;
     ObjectId btrId = ObjectId.Null;
     using (Transaction trans = database.TransactionManager.StartTransaction())
     {
         BlockTable bt = (BlockTable)database.BlockTableId.GetObject(OpenMode.ForWrite);
         if (bt.Has(blockName)) { btrId = bt[blockName]; }
         if (!bt.Has(blockName))
         {
             using (BlockTableRecord btr = new BlockTableRecord() { Name = blockName })
             { 
                 foreach (var objectId in objectIds)
                 {
                     Entity ent = trans.GetObject(objectId, OpenMode.ForRead, true) as Entity; 
                     if (ent == null) continue;
                     btr.AppendEntity(ent);
                 }
                 btrId = bt.Add(btr);
                 trans.AddNewlyCreatedDBObject(btr, true);
             }
             trans.Commit();
         }
     }
     return btrId;
 }


}

 

I selected three circles created by handle , then I got an ERROR IT SAYS : 

 Autodesk.AutoCAD.Runtime.Exception: eAlreadyInDb
在 Autodesk.AutoCAD.DatabaseServices.BlockTableRecord.AppendEntity(Entity entity)
在 SEPD.ACAD.Extension.BlockExtension.ToBlockTable(IEnumerable`1 objectIds, String blockName) 位置 D:\WORKSPACE\CODE_CAD\SEPD.ACAD.Extension\SEPD.ACAD.Extension\BlockExtension.cs:行号 226
在 SEPD.ACAD.Extension._ExtensionTest_.BlockCreate023() 位置 D:\WORKSPACE\CODE_CAD\SEPD.ACAD.Extension\SEPD.ACAD.Extension\_ExtensionTest_.cs:行号 645
在 Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
在 Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
在 Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
在 Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()

 

seems some problem heppend at code "btr.AppendEntity(ent)"

 

TIP:

If I quit use the SelectEntity Function , just create circle by code , then , everything is fine;

 

 

0 Likes
Accepted solutions (1)
713 Views
2 Replies
Replies (2)
Message 2 of 3

_gile
Consultant
Consultant
Accepted solution

Hi,

The entities you're trying to add to the block definition (BlockTableRecord) are already owned by the BlockTableRecord of the space in which you selected them.

You have to create a copy (clone) of each selected entity and append these clones to the block definition.

 

public static ObjectId ToBlockTableRecord(this IEnumerable<ObjectId> objectIds, string blockName)
{
    var database = HostApplicationServices.WorkingDatabase;
    using (Transaction trans = database.TransactionManager.StartTransaction())
    {
        BlockTable bt = (BlockTable)trans.GetObject(database.BlockTableId, OpenMode.ForRead);

        // if the block definition already exists in the block table, return its ObjectId
        if (bt.Has(blockName))
            return bt[blockName];

        // Create a new block definition
        trans.GetObject(database.BlockTableId, OpenMode.ForWrite);
        var btr = new BlockTableRecord() { Name = blockName };
        var btrId = bt.Add(btr);
        trans.AddNewlyCreatedDBObject(btr, true);

        // Deep clone each entity in the block definition
        var mapping = new IdMapping();
        database.DeepCloneObjects(new ObjectIdCollection(objectIds.ToArray()), btrId, mapping, false);
        trans.Commit();
        return btrId;
    }
}

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 3

1755384511
Participant
Participant
Nice job, I have succeeded, many thanks!
0 Likes