protected override void TrySolveInstance(IGH_DataAccess DA) { var elementList = new List <Types.IGH_Element>(); if (!DA.GetDataList("Elements", elementList)) { return; } try { var elementGroups = elementList. GroupBy(x => x.Document). ToArray(); if (elementGroups.Length > 0) { var transactionGroups = new Queue <DB.TransactionGroup>(); try { var Succeeded = true; var Deleted = new List <Types.Element>(); var Modified = new List <Types.Element>(); foreach (var elementGroup in elementGroups) { var doc = elementGroup.Key; // Start a transaction Group to be able to rollback in case changes in different documents fails. { var group = new DB.TransactionGroup(doc, Name); if (group.Start() != DB.TransactionStatus.Started) { group.Dispose(); continue; } transactionGroups.Enqueue(group); } ClassifyElementIds(elementGroup, out var elements, out var types); // Step 1. Purge non ElementTypes Succeeded &= Purge(doc, elements, Deleted, Modified); // Step 2. Check if ElementTypes to be purged are still in use in the model by any Instance if (types.Count > 0) { var typesInUse = new List <DB.ElementId>(types.Count); // Remove purgable ElementTypes from types if (doc.GetPurgableElementTypes(out var purgableTypes)) { foreach (var type in types) { if (!purgableTypes.Contains(type)) { typesInUse.Add(type); } } } // Post a FailureMessage in case we have non purgable ElementTypes on types if (typesInUse.Count > 0) { using (var transaction = NewTransaction(doc)) { transaction.Start(); using (var message = new DB.FailureMessage(DBX.ExternalFailures.ElementFailures.FailedToPurgeElement)) { message.SetFailingElements(typesInUse); doc.PostFailure(message); } CommitTransaction(doc, transaction); } Succeeded &= false; } } // Step 3. Purge ElementTypes // Types include typesInUse in order to get information about Deleted and Modified elements. Succeeded &= Purge(doc, types, Deleted, Modified); } if (Succeeded && !Simulated) { deletedElements += Deleted.Count; // Transactions in all documents succeded, it's fine to assimilate all changes as one. while (transactionGroups.Count > 0) { using (var group = transactionGroups.Dequeue()) { group.Assimilate(); } } } DA.SetData("Succeeded", Succeeded); DA.SetDataList("Deleted", Deleted); DA.SetDataList("Modified", Modified); } catch (Autodesk.Revit.Exceptions.ArgumentException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements cannot be deleted or are invalid."); DA.SetData("Succeeded", false); } finally { // In case we still have transaction groups here something bad happened foreach (var group in transactionGroups.Cast <DB.TransactionGroup>().Reverse()) { using (group) { group.RollBack(); } } } } } catch (NullReferenceException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements are Null."); } }
protected override void TrySolveInstance(IGH_DataAccess DA) { var elementList = new List <Types.IGH_Element>(); if (!DA.GetDataList("Elements", elementList)) { return; } try { var elementGroups = elementList. GroupBy(x => x.Document). ToArray(); if (elementGroups.Length > 0) { var transactionGroups = new Queue <DB.TransactionGroup>(); try { var _Deleted_ = Params.IndexOfOutputParam("Deleted"); var _Modified_ = Params.IndexOfOutputParam("Modified"); var Succeeded = true; var Deleted = _Deleted_ < 0 ? default : new List <Types.Element>(); var Modified = _Modified_ < 0 ? default : new List <Types.Element>(); foreach (var elementGroup in elementGroups) { var doc = elementGroup.Key; // Start a transaction Group to be able to rollback in case changes in different documents fails. { var group = new DB.TransactionGroup(doc, Name); if (group.Start() != DB.TransactionStatus.Started) { group.Dispose(); continue; } transactionGroups.Enqueue(group); } var elements = new HashSet <DB.ElementId>(elementGroup.Select(x => x.Id)); var result = Delete(doc, elements, Deleted, Modified); if (result < 0) { Succeeded = false; } else { deletedElements += result; } } if (Succeeded && !Simulated) { // Transactions in all documents succeded, it's fine to assimilate all changes as one. while (transactionGroups.Count > 0) { using (var group = transactionGroups.Dequeue()) { group.Assimilate(); } } } else { deletedElements = 0; } DA.SetData("Succeeded", Succeeded); if (_Deleted_ >= 0) { DA.SetDataList(_Deleted_, Deleted); } if (_Modified_ >= 0) { DA.SetDataList(_Modified_, Modified); } } catch (Autodesk.Revit.Exceptions.ArgumentException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements cannot be deleted or are invalid."); DA.SetData("Succeeded", false); } finally { // In case we still have transaction groups here something bad happened foreach (var group in transactionGroups.Cast <DB.TransactionGroup>().Reverse()) { using (group) { group.RollBack(); } } transactionGroups.Clear(); } } } catch (NullReferenceException) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "One or many of the elements are Null."); } }