Two transactions within command

Two transactions within command

Anonymous
Not applicable
1,197 Views
2 Replies
Message 1 of 3

Two transactions within command

Anonymous
Not applicable

Hello,

 

I am having some c# issues which I haven't managed to completely narrow down but think it may be something to do with having two transactions occurring within a command.

 

My code below is to enable a block to be grouped within a new group with a specific name, but I also want the user to have the option to be able to delete all existing groups first.

 

[CommandMethod("CG")] // This command will create a group based on the objectid and add the block to the group
public static void CreateGroup() {

        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;
        Transaction tr = db.TransactionManager.StartTransaction();
        
        //Get block table from drawing
        BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
       

        PromptEntityOptions peo = new PromptEntityOptions("\nSelect block type");
        peo.SetRejectMessage("Must be a block");
        peo.AddAllowedClass(typeof(BlockReference), false);
        PromptEntityResult per = ed.GetEntity(peo);
        DBDictionary gd = (DBDictionary)tr.GetObject(db.GroupDictionaryId, OpenMode.ForRead);
        if (per.Status != PromptStatus.OK)
            return;
// Request to delete all groups PromptKeywordOptions pko = new PromptKeywordOptions("\nWould you like delete groups?"); pko.Keywords.Add("Yes"); pko.Keywords.Add("No"); var pkr = ed.GetKeywords(pko); if (pkr.StringResult == "Yes") { using (tr) { foreach (DBDictionaryEntry grp in gd) { Group group = (Group)tr.GetObject(grp.Value, OpenMode.ForRead); //group.UpgradeOpen(); //group.Erase(); } tr.Commit(); } }
//Create sequentially named group for each block and add each block to the group dynamic bkID = per.ObjectId; ObjectIdCollection refid = bkID.BlockTableRecord.GetBlockReferenceIds(true, true); using(tr) { foreach (ObjectId id in refid) { int i = refid.IndexOf(id); string grpName = "PREFIX" + i.ToString("0000"); Group grp = new Group("GROUP DESCRIPTION", true); gd.UpgradeOpen(); ObjectId grpID = gd.SetAt(grpName, grp); tr.AddNewlyCreatedDBObject(grp, true); grp.Append(id); } tr.Commit(); } }

The two components of the code (the group delete and group) creation work perfectly when excecuted as their individual commands however when trying to combine the two, it crashes CAD.

 

I'm quite new to C# and coding in general so there may well be some appalling errors in there but any help is appreciated.

 

Cheers

 

Matt

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

_gile
Consultant
Consultant
Accepted solution

Hi,

 

You shouldn't start a transaction an use it outside the using statement block code.

You open the BlockTable, the model space BlockTableRecord, the group dictionary and potentially several groups outside the using scope these object won't be disposed with the transaction.

Then, you cannot re-use the same transaction after you disposed it.

 

The simplest way is to use a single transaction:

 

        [CommandMethod("CG")] // This command will create a group based on the objectid and add the block to the group
        public static void CreateGroup()
        {

            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
// Start a transaction and a using statement using (Transaction tr = db.TransactionManager.StartTransaction()) { //Get block table from drawing BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite); PromptEntityOptions peo = new PromptEntityOptions("\nSelect block type"); peo.SetRejectMessage("Must be a block"); peo.AddAllowedClass(typeof(BlockReference), false); PromptEntityResult per = ed.GetEntity(peo); DBDictionary gd = (DBDictionary)tr.GetObject(db.GroupDictionaryId, OpenMode.ForRead); if (per.Status != PromptStatus.OK) return; // Request to delete all groups PromptKeywordOptions pko = new PromptKeywordOptions("\nWould you like delete groups?"); pko.Keywords.Add("Yes"); pko.Keywords.Add("No"); var pkr = ed.GetKeywords(pko); if (pkr.StringResult == "Yes") { foreach (DBDictionaryEntry grp in gd) { Group group = (Group)tr.GetObject(grp.Value, OpenMode.ForRead); //group.UpgradeOpen(); //group.Erase(); } } //Create sequentially named group for each block and add each block to the group dynamic bkID = per.ObjectId; ObjectIdCollection refid = bkID.BlockTableRecord.GetBlockReferenceIds(true, true); foreach (ObjectId id in refid) { int i = refid.IndexOf(id); string grpName = "PREFIX" + i.ToString("0000"); Group grp = new Group("GROUP DESCRIPTION", true); gd.UpgradeOpen(); ObjectId grpID = gd.SetAt(grpName, grp); tr.AddNewlyCreatedDBObject(grp, true); grp.Append(id); } tr.Commit(); } }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 3

Anonymous
Not applicable

Excellent! Thanks so much for your help!!

0 Likes