【Revit二次开发】事务和事务处理(Transaction and FailureHandlingOptions)
事务基础
事务是将一系列修改Revit模型的操作提交至文档的这样一种对象。 任何一个对文档修改的操作都需要包含在-一个打开的属于该文档的事务中,否则就会有异常抛出。任何修改都要在事务提交后才写人文档。在一个事务中进行的所有修改都能被撤销。在任何时候,一个文档当前只能有一个打开的事务,但在一个事务中可以有一个或多个修改模型的操作。
事务是将一系列修改Revit模型的操作提交到文档的一种对象。任何一个对文档修改的操作都要包含在一个打开的属于该文档的食物中。
和事务有关的主要有三个类:
- Transaction事务
- SubTransaction子事务
- TransactionGroup事务组
注意:
①用于IExternalCommand 的TransactionMode属性会影响该命令在被执行时Revi对事务的处理。
②如果一个事务从其他线程或在模态对话框之外启动会导致异常发生。事务只能从API支持的环境中启动,比如外部命令、事件等。
通用事务方法
方法 | 描述 |
---|---|
Start | 启动事务 |
Commit | 结束事务并提交所有的修改到文档中 |
RollBack | 结束事务并撤销对文档所做的所有的修改 |
GetStatus | 返回当前事务状态 |
Transaction类
要修改Revil 文档中的模型就需要一个Transaction。 在同一时间,只有一个Transaction可以被打开,不允许嵌套。每个Transaction需要一个名字,当这个Transaction被成功提交后,这个名字会被显示在Undo菜单里。
FailureHandlingOptions
控制在事务结束时如何处理故障(如果在事务期间发生了任何故障)的选项。
编写代码
using System;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace HelloRevitTransaction
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class RevitTransactionCmd : IExternalCommand
{
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
//获取文档
Document doc = commandData.Application.ActiveUIDocument.Document;
//会修改Revit文档模型的操作需要事务
//创建transaction来执行命令
// 任何Transaction要放在 “using”中创建来保证它被正确的结束,而不会影响到其他地方
using (Transaction transaction = new Transaction(doc))
{
if (transaction.Start("事务") == TransactionStatus.Started)
{
Line line = Line.CreateBound(XYZ.Zero, XYZ.BasisX);
Wall wall = Wall.Create(doc, line, new ElementId(311), false);
//提交
//由于种种原因,如果修改或创建的模型不正确,
//这个Transaction可能不会被正确提交
//如果一个Transaction失败了或被用户取消了,
//那么返回的状态就是RolledBack,而不是Committed。
try
{
TaskDialog taskDialog = new TaskDialog("Revit");
taskDialog.MainContent = "Click either [OK] to Commit, or [Cancel] to Roll back the transaction.";
TaskDialogCommonButtons buttons = TaskDialogCommonButtons.Ok | TaskDialogCommonButtons.Cancel;
taskDialog.CommonButtons = buttons;
if (TaskDialogResult.Ok == taskDialog.Show())
{
if (TransactionStatus.Committed != transaction.Commit())
{
TaskDialog.Show("事务入门", "提交失败!");
}
}
}
//回滚
catch
{
transaction.RollBack();
}
}
}
return Autodesk.Revit.UI.Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Autodesk.Revit.UI.Result.Failed;
}
}
}
}
事务提交后,Revit会管理事务中发生的错误和警告。当错误发生时,事务将会抛出异常。当警告发生时,Revit的故障处理程序将会以默认的方式处理警告。
public void CompoundOperation(Autodesk.Revit.DB.Document document)
{
// 所有TransactionGroup要用“using”来创建来保证它的正确结束
using (TransactionGroup transGroup = new TransactionGroup(document, "Level and Grid"))
{
if (transGroup.Start() == TransactionStatus.Started)
{
// 我们打算调用两个函数,每个都有一个独立的事务
// 我们打算这个组合操作要么成功,要么失败
// 只要其中有一个失败,我们就撤销所有操作
if (CreateLevel(document, 25.0) && CreateGrid(document, new XYZ(0, 0, 0), new XYZ(10, 0, 0)))
{
// Assimilate函数会将这两个事务合并成一个,并只显示TransactionGroup的名字
// 在Undo菜单里
transGroup.Assimilate();
}
else
{
// 如果有一个操作失败了,我们撤销在这个事务组里的所有操作
transGroup.RollBack();
}
}
}
}
public bool CreateLevel(Autodesk.Revit.DB.Document document, double elevation)
{
using (Transaction transaction = new Transaction(document, "Creating Level"))
{
// 必须启动事务来修改文档
if (TransactionStatus.Started == transaction.Start())
{
if (null != document.Create.NewLevel(elevation))
{
return (TransactionStatus.Committed == transaction.Commit());
}
// 如果不能创建层,撤销这个事务
transaction.RollBack();
}
}
return false;
}
public bool CreateGrid(Autodesk.Revit.DB.Document document, XYZ p1, XYZ p2)
{
using (Transaction transaction = new Transaction(document, "Creating Grid"))
{
if (TransactionStatus.Started == transaction.Start())
{
Line gridLine = Line.CreateBound(p1, p2);
if ((null != gridLine) && (null != document.Create.NewGrid(gridLine)))
{
if (TransactionStatus.Committed == transaction.Commit())
{
return true;
}
}
// 如果不能创建网格,撤销这个事务
transaction.RollBack();
}
}
return false;
}
TransactionHandleCmd类功能为在同一位置绘制三堵墙,并在事务中使用自定义的故障处理选项,自定义的方式是把SameElementProcessor作为故障预处理器Set到故障处理选项中。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using TransactionHandleDemo;
namespace TransactionHandleCmd
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
public class Class1 : IExternalCommand
{
//TransactionHandleCmd类功能为在同一位置绘制三堵墙,并在事务中使用自定义的故障处理选项
//自定义的方式是把SameElementProcessor作为故障预处理器Set到故障处理选项中
public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
Document doc = commandData.Application.ActiveUIDocument.Document;
Transaction tran = new Transaction(doc);
tran.Start("创建同名标高");
//Returns the current failure handling options.
FailureHandlingOptions failureOptions = tran.GetFailureHandlingOptions();
//Sets options for handling failures to be used when the transaction is being committed or rolled back.
failureOptions.SetFailuresPreprocessor(new SameElementProcessor());
tran.SetFailureHandlingOptions(failureOptions);
Line line = Line.CreateBound(XYZ.Zero, XYZ.BasisX * 5);
Level level = getLevel(doc);
Wall.Create(doc, line, level.Id, false);
Wall.Create(doc, line, level.Id, false);
Wall.Create(doc, line, level.Id, false);
tran.Commit();
return Autodesk.Revit.UI.Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Autodesk.Revit.UI.Result.Failed;
}
}
private Level getLevel(Document doc)
{
return (Level)new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels)
.OfClass(typeof(Level)).FirstElement();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
namespace TransactionHandleDemo
{
//如果提供了该接口,则在事务结束时发现故障时调用该接口。可以在事务对象的失败处理选项中设置此接口的实例。
public class SameElementProcessor : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
failuresAccessor.DeleteAllWarnings();
return FailureProcessingResult.Continue;
}
}
}
本文来自博客园,作者:Patrick-Rex,转载请注明原文链接:https://www.cnblogs.com/patrickrex/p/18028763
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升