First of all, let me explain why I wrote the code this way. Normally, I would create a polyline in this manner and then append it to a group, like this.
Polyline polyline = new Polyline();
polyline.AddVertexAt(0, new Point2d(vertex1.X, vertex1.Y), 0, 0, 0);
polyline.AddVertexAt(1, new Point2d(vertex2.X, vertex2.Y), 0, 0, 0);
polyline.AddVertexAt(2, new Point2d(vertex3.X, vertex3.Y), 0, 0, 0);
polyline.Closed = true;
btr.AppendEntity(polyline);
trans.AddNewlyCreatedDBObject(polyline, true);
DBDictionary groupDict = (DBDictionary)tr.GetObject(db.GroupDictionaryId, OpenMode.ForWrite);
string groupName = "Group_Example"
Group group = new Group(groupName, true);
group.Append(polyline.ObjectId);
r.AddNewlyCreatedDBObject(group, true);
However, when the number of Entites to be drawn exceeds 10,0000, the number of objects managed by the transaction increases each time AddNewlyCreatedDBObject is called. As a result, the time required for tr.Commit becomes significantly longer.
So, since simply creating polyline instances does not require a transaction, I tried creating the polyline objects separately and then saving them to the BlockTableRecord in a different transaction. Like this.
List<Tuple<Polyline, DBText>> groupedEntities = new List<Tuple<Polyline, DBText>>(100000);
for (int i = 0; i < 100000; i++)
{
Polyline polyline = new Polyline();
polyline.AddVertexAt(0, new Point2d(i * 10, 0), 0, 0, 0);
polyline.AddVertexAt(1, new Point2d(i * 10 + 5, 0), 0, 0, 0);
polyline.AddVertexAt(2, new Point2d(i * 10 + 5, 5), 0, 0, 0);
polyline.AddVertexAt(3, new Point2d(i * 10, 5), 0, 0, 0);
polyline.Closed = true;
polyline.ColorIndex = 2;
DBText text = new DBText();
text.Position = new Point3d(i * 10 + 2.5, 2.5, 0);
text.Height = 1.0;
text.TextString = $"ID {i}";
groupedEntities.Add(new Tuple<Polyline, DBText>(polyline, text));
}
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
DBDictionary groupDict = trans.GetObject(db.GroupDictionaryId, OpenMode.ForWrite) as DBDictionary;
int count = 1;
foreach (var entity in groupedEntities)
{
Polyline pl = entity.Item1;
DBText txt = entity.Item2;
string groupName = "Large_Group_Example"+count++;
Group group = new Group(groupName, true);
btr.AppendEntity(pl);
trans.AddNewlyCreatedDBObject(pl, true);
group.Append(pl.ObjectId);
btr.AppendEntity(txt);
trans.AddNewlyCreatedDBObject(txt, true);
group.Append(txt.ObjectId);
ObjectId groupId = groupDict.SetAt(groupName, group);
trans.AddNewlyCreatedDBObject(group, true);
}
trans.Commit();
}
However, even when retrieving the polyline instances elsewhere, an eNotOpenForWrite error occurred if tr.AddNewlyCreatedDBObject was not called.
this meant that the entity had to be registered in the transaction for it to be added to the Group. So, I started thinking about how to properly retrieve the object from the transaction without using tr.AddNewlyCreatedDBObject.(Ah also I tried upgradeOpen too)
I concluded that the best way would be to use
DBObject dBObject = tr.GetObject(entity.ObjectId, OpenMode.ForRead);
By following this approach, I first appended the object to btr.AppendEntity(), allowing it to receive an ObjectId. Then, I retrieved the object using tr.GetObject() and successfully added it to the Group with Group.Append().
ObjectIdCollection objCollection = new ObjectIdCollection();
foreach (Entity entity in groupEntities)
{
btr.AppendEntity(entity);
DBObject dBObject = tr.GetObject(entity.ObjectId, OpenMode.ForRead);
//tr.AddNewlyCreatedDBObject(entity, true);
objCollection.Add(entity.ObjectId);
}
//...
group.Append(objCollection)
As a result, I confirmed that the commit time was significantly faster. However, the object did not appear on the screen.
The fundamental and biggest issue is that the drawing file I am working with is extremely large. In smaller drawings, committing 500 objects takes less than 10 milliseconds, but in the drawing I am using, committing the same amount takes approximately 0.5 seconds.