チームで作業する場合、単一のユーザの場合には発生しない、Revit API アドインの操作性の問題が発生することがあります。特に、アドインの設計方法によって、編集の競合が回避できることもあれば発生することもあります。たとえば、アドインが何千もの要素の編集を行おうとした場合、これらの要素すべてをローカル ユーザにチェックアウトする必要があり、中央との同期が完了するまで、他のユーザはそれらの要素を使用できなくなります。または、要素のいくつかが他のユーザにチェックアウトされていて、編集できない場合があります。ワークシェアリングされたモデルに API から変更を加える場合は、この点に注意する必要があります。
基本的なモデル編集ワークフローは次のようになります。
操作 | 例 | 重要である理由 |
---|---|---|
ユーザがモデルの一部の要素を変更します | ユーザが壁をドラッグします | これらの変更は「ユーザによる変更」となります。ユーザが変更を加えるには、これらの要素を借用する必要があります。 |
Revit は必要に応じて、モデルに追加のデータを再生成します | 結合された壁が移動され、床が更新され、屋根が更新され、部屋が更新され、部屋タグはそれらが部屋に残っているかどうかをチェックします | これらの変更は「システムによる変更」となります。変更された場合でも、他のユーザはそのまま使用できます。 |
ほとんどの API の変更は「ユーザによる変更」であり、ローカル ユーザが手動で変更を加えた場合と同様に処理されます。外部コマンド、マクロ、イベントからの呼び出しの場合にこのように処理されます。唯一の例外はアップデータから行われた変更であり、これはシステムによる変更として扱われます。
コード領域: ワークシェアリング エラーを抑止 |
public static void TryToEditGeometricElement(Element elem, bool useFailureHandlingOpts) { Document doc = elem.Document; using (Transaction t = MakeTransaction(doc, "Move element", useFailureHandlingOpts)) { t.Start(); ElementTransformUtils.MoveElement(doc, elem.Id, new XYZ(1, 1, 0)); t.Commit(); } } private static Transaction MakeTransaction(Document doc, string name, bool useFailureHandlingOpts) { Transaction t = new Transaction(doc, name); if (useFailureHandlingOpts) { FailureHandlingOptions opts = t.GetFailureHandlingOptions(); opts.SetClearAfterRollback(true); opts.SetFailuresPreprocessor(new WorksharingErrorsPreprocessor()); t.SetFailureHandlingOptions(opts); } return t; } |
WorksharingUtils クラスを使用すると、要素とワークセットの所有権を修正できます。CheckoutElements()メソッドは、できるだけ多くの指定した要素の現在のユーザに所有権を取得し、CheckoutWorksets()メソッドはワークセットに対して同じ処理を行います。これらのメソッドは、編集を実行する前に要素をチェックアウトするのに役立ちます。RelinquishOwnership()メソッドは、指定された RelinquishOptions に基づいて、現在のユーザによって所有されている要素とワークセットを放棄します。
パフォーマンスを最適化するには、多数の細かな呼び出しではなく、一度の大きな呼び出しですべての要素やワークセットをチェックアウトし、項目を破棄します。
次の例では、編集前に特定の要素のチェックアウトを試み、問題が発生した場合に、ユーザに対してメッセージを発行します。
コード領域: 要素をチェックアウト |
public static bool AttemptToCheckoutInAdvance(Element element) { Document doc = element.Document; String categoryName = element.Category.Name; // Checkout attempt ICollection<ElementId> checkedOutIds = WorksharingUtils.CheckoutElements(doc, new ElementId[] { element.Id }); // Confirm checkout bool checkedOutSuccessfully = checkedOutIds.Contains(element.Id); if (!checkedOutSuccessfully) { TaskDialog.Show("Element is not checked out", "Cannot edit the " + categoryName + " element - " + "it was not checked out successfully and may be checked out to another."); return false; } // If element is updated in central or deleted in central, it is not editable ModelUpdatesStatus updatesStatus = WorksharingUtils.GetModelUpdatesStatus(doc, element.Id); if (updatesStatus == ModelUpdatesStatus.DeletedInCentral || updatesStatus == ModelUpdatesStatus.UpdatedInCentral) { TaskDialog.Show("Element is not up to date", "Cannot edit the " + categoryName + " element - " + "it is not up to date with central, but it is checked out."); return false; } return true; } |
次の例は、すべてのビュー ワークセットをチェックアウトする方法を表しています。
コード領域: ワークセットをチェックアウト |
void CheckoutAllViewWorksets(Document doc) { FilteredWorksetCollector collector = new FilteredWorksetCollector(doc); // find all view worksets collector.OfKind(WorksetKind.ViewWorkset); ICollection<WorksetId> viewworksets = collector.ToWorksetIds(); ICollection<WorksetId> checkoutworksets = WorksharingUtils.CheckoutWorksets(doc, viewworksets); TaskDialog.Show("Checked out worksets", "Number of worksets checked out: " + checkoutworksets.Count); } |