チームで作業する場合、単一のユーザの場合には発生しない、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);
}
|