事务,一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元 (unit)。
对于初学者来说,从字面上难以理解什么是事务。下面我试着通过讲述事务的作用及特性来帮助您初步了解事务。
- 事务将多个数据库操作 “合并” 为一个;
- 事务开启后,可以通过 GetObject 方法来打开一个对象;
- 事务可以提交(commit),也可以回滚(abort);
- 事务也可以嵌套;
- 通过事务管理器启动和管理事务。
事务是将一系列操作作为一个单元执行,要么成功,要么失败,回滚到最初状态。在事务处理术语中,事务要么提交,要么中止。若要提交事务,所有参与者都必须保证对数据的任何更改是永久的。不论系统崩溃或是发生其他无法预料的事件,更改都必须是持久的。只要有一个参与者无法做出此保证,整个事务就会失败。事务范围内的所有数据更改将回滚到特定设置点。
事务是恢复和并发控制的基本单位。
事务应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。
- 原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
- 一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
事务将多个操作紧密联系到一起,这样就能保证有联系的两种操作的一致性、以及数据的完整性。
事务用于将多个对象的多个操作分组在一起作为单个操作。 一旦事务启动,您可以使用 GetObject 函数打开一个对象。
当您处理使用 GetObject 打开的对象时,事务管理器将跟踪正在对象进行的更改。 您创建和添加到数据库的任何新对象也应该添加到事务以及 AddNewlyCreatedDBObject 函数。 一旦对象被编辑或添加到数据库中,您可以保存对数据库所做的更改,并使用事务管理器创建的事务对象中的 Commit 函数关闭所有打开的对象。 完成交易后,调用 Dispose 函数关闭事务。
从当前数据库的 TransactionManager 属性访问事务管理器。一旦对事务管理器进行引用,您可以使用以下方法之一来启动或获取事务:
StartTransaction - 通过创建一个 Transaction 对象的新实例来启动一个新的事务。当您需要多次写入对象并控制如何通过使用不同的嵌套级别回滚更改时,请使用此方法。
StartOpenCloseTransation - 创建一个 OpenCloseTransaction 对象,其行为类似于 Transaction 对象,它包装对象的 Open 和 Close 方法,从而更容易地关闭所有已打开的对象,而不必显式关闭每个已打开的对象。推荐用于可能被称为未知次数的支持或效用函数,并在使用大多数事件处理程序时使用。
一旦有一个事务或 OpenCloseTransaction 对象,使用 GetObject 方法来打开存储在数据库中的对象进行读取或写入。 GetObject 方法返回一个可以转换为它所代表的实际对象类型的 DBObject。
在事务处理期间打开的所有打开的对象都将在事务结束时关闭。要结束事务,请调用事务对象的 Dispose 方法。如果使用 “使用和结束使用” 关键字来指示事务的开始和结束,则不需要调用 Dispose 方法。
处理事务之前,您应该提交使用 Commit 方法进行的任何更改。如果在事务处理之前未提交更改,则所做的任何更改都将回滚到事务开始之前的状态。
可以启动多个事务。可以使用 TransactionManager 对象的 NumberOfActiveTransactions 属性检索活动事务的数量,而可以使用 TopTransaction 属性检索最高或最新的事务。
事务可以嵌套在另一个内部,以便回滚在执行例程期间所做的一些更改。
我们操作cad最主要的目的就是读取和修改或者删除数据,因为内容较多,在此我们先讲一下基础,后续慢慢讲解。
1、cad数据读取和修改前都要进行锁定操作,以避免一个文档被多个用户修改而发生冲突。
Database db = HostApplicationServices.WorkingDatabase; //当前数据库
using (Transaction tr = db.TransactionManager.StartTransaction()) //using,自动调用Dispose方法
{
//处理过程
tr.Commit();
//事务提交
}
2、我们在处理过程中输入自己想要的代码就可以正常操作了,要不然会报错的。
然后我们就要进行图形数据的读取了,但是因为内容太多,所以会后续更新,在此简单附上一个在屏幕上选择单个实体的代码。
public static Entity Select(string word)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database; Editor ed = doc.Editor;
Entity entity = null;
PromptEntityResult ent = ed.GetEntity(word);
if (ent.Status == PromptStatus.OK)
{
using (Transaction transaction = db.TransactionManager.StartTransaction())
{
entity = (Entity)transaction.GetObject(ent.ObjectId, OpenMode.ForWrite, true);
transaction.Commit();
}
}
return entity;
}
3、我们读取的数据一般都是多个,所以要进行遍历筛选处理。
using (Transaction trans = db.TransactionManager.StartTransaction())
{
foreach (DBObject ob in texts)
{
DBText text = (DBText)transaction.GetObject(ob.ObjectId, OpenMode.ForWrite, true);
………………………………操作内容
}
trans.Commit();
}