5.1.2.3. Вложенные транзакции

Источник здесь.[перевод не проверен] [переводчик: bandero]

    Транзакции можно вкладывать одна в другую. У вас может быть внешняя транзакция для отмены всех изменений, и вложенные транзакции для отмены части изменений.  Когда вы работаете с вложенными транзакциями, вы начинаете с главной транзакции, которая будет внешней для остальных транзакций.

    Когда вы запускаете новую транзакцию, она добавляется в предыдущую транзакцию. Вложенная транзакция должна быть зафиксирована или завершена в рамках создавшей её транзакции. Так, если вы имеете три транзакции, вы должны закрыть третью или самую внутреннюю первой, затем вторую и наконец, первую.  Если вы отмените первую транзакцию, изменения во всех трёх транзакциях отменятся.

Использование вложенной транзакции для создания и изменения объектов

    Следующий пример демонстрирует использование трёх транзакций для создания объектов Круга (Circle) и Линии (Line), а затем изменения их цвета. Цвет круга изменяется во второй и третьей транзакциях, но так как третья транзакция отменена, в базу сохранятся только изменения сделанные в первой и второй транзакциях. Дополнительно, в командную строку будет выводится число активных транзакций при её создании и закрытии.

Код VB.NET

   1:  Imports Autodesk.AutoCAD.Runtime 
   2:  Imports Autodesk.AutoCAD.ApplicationServices 
   3:  Imports Autodesk.AutoCAD.DatabaseServices 
   4:  Imports Autodesk.AutoCAD.Geometry 
   5:  Imports Autodesk.AutoCAD.EditorInput 
   6:   
   7:  <CommandMethod("NestedTransactions")> _ 
   8:  Public Sub NestedTransactions() 
   9:   
  10:      '' Получаем текущий документ и базу данных 
  11:      Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument 
  12:      Dim acCurDb As Database = acDoc.Database 
  13:   
  14:      '' Создание ссылки на Менеджер Транзакций 
  15:      Dim acTransMgr As Autodesk.AutoCAD.DatabaseServices.TransactionManager 
  16:      acTransMgr = acCurDb.TransactionManager 
  17:   
  18:      '' Создание новой транзакции 
  19:      Using acTrans1 As Transaction = acTransMgr.StartTransaction() 
  20:   
  21:          '' Записываем текущее число активных транзакций 
  22:          acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _ 
  23:          acTransMgr.NumberOfActiveTransactions.ToString()) 
  24:   
  25:          '' Открытие таблицы Блоков для чтения 
  26:          Dim acBlkTbl As BlockTable 
  27:          acBlkTbl = acTrans1.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) 
  28:   
  29:          '' Открытие записи Таблицы Блоков Модели для записи 
  30:          Dim acBlkTblRec As BlockTableRecord 
  31:          acBlkTblRec =         acTrans1.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), _ 
  32:          OpenMode.ForWrite) 
  33:   
  34:          '' Создание Круга с радиусом 3 в точке 5,5 
  35:          Dim acCirc As Circle = New Circle() 
  36:          acCirc.SetDatabaseDefaults() 
  37:          acCirc.Center = New Point3d(5, 5, 0) 
  38:          acCirc.Radius = 3 
  39:   
  40:          '' Добавление нового объекта в Модель и транзакцию 
  41:          acBlkTblRec.AppendEntity(acCirc) 
  42:          acTrans1.AddNewlyCreatedDBObject(acCirc, True) 
  43:   
  44:          '' Создание второй транзакции 
  45:          Using acTrans2 As Transaction = acTransMgr.StartTransaction() 
  46:          
  47:              acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _ 
  48:              acTransMgr.NumberOfActiveTransactions.ToString()) 
  49:   
  50:              '' Изменение цвета у круга 
  51:              acCirc.ColorIndex = 5 
  52:   
  53:              '' Получаем объект который будет добавлен к транзакции 1 и устанавливаем ему цвет 5 
  54:              Dim acLine As Line = New Line(New Point3d(2, 5, 0), New Point3d(10, 7, 0)) 
  55:              acLine.SetDatabaseDefaults() 
  56:              acLine.ColorIndex = 3 
  57:   
  58:              '' Добавление нового объекта в Модель и транзакцию 
  59:              acBlkTblRec.AppendEntity(acLine) 
  60:              acTrans2.AddNewlyCreatedDBObject(acLine, True) 
  61:   
  62:              '' Создание третьей транзакции 
  63:              Using acTrans3 As Transaction = acTransMgr.StartTransaction() 
  64:   
  65:                  acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _ 
  66:                  acTransMgr.NumberOfActiveTransactions.ToString()) 
  67:   
  68:                  '' Изменение цвета у круга 
  69:                  acCirc.ColorIndex = 3 
  70:   
  71:                  '' Обновление экрана чертежа 
  72:                  acDoc.Editor.WriteMessage(vbLf) 
  73:                  acDoc.Editor.Regen() 
  74:   
  75:                  '' Запрос принятия или отказа изменений в третьей транзакции 
  76:                  Dim pKeyOpts As PromptKeywordOptions = New PromptKeywordOptions("") 
  77:                  pKeyOpts.Message = vbLf & "Keep color change " 
  78:                  pKeyOpts.Keywords.Add("Yes") 
  79:                  pKeyOpts.Keywords.Add("No") 
  80:                  pKeyOpts.Keywords.Default = "No" 
  81:                  pKeyOpts.AllowNone = True 
  82:   
  83:                  Dim pKeyRes As PromptResult = acDoc.Editor.GetKeywords(pKeyOpts) 
  84:   
  85:                  If pKeyRes.StringResult = "No" Then 
  86:                      '' Отказ изменений в 3 транзакции 
  87:                      acTrans3.Abort() 
  88:                  Else 
  89:                      '' Сохранение изменений в 3 транзакции 
  90:                      acTrans3.Commit() 
  91:                  End If 
  92:   
  93:              '' Высвобождение объекта транзакции 
  94:              End Using 
  95:   
  96:              acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _ 
  97:              acTransMgr.NumberOfActiveTransactions.ToString()) 
  98:   
  99:              '' Принятие изменений во 2 транзакции 
 100:              acTrans2.Commit() 
 101:          End Using 
 102:   
 103:          acDoc.Editor.WriteMessage(vbLf & "Number of transactions active: " & _ 
 104:          acTransMgr.NumberOfActiveTransactions.ToString()) 
 105:   
 106:          '' Принятие изменений в 1 транзакции 
 107:          acTrans1.Commit() 
 108:      End Using 
 109:  End Sub

Код C#

   1:  using Autodesk.AutoCAD.Runtime; 
   2:  using Autodesk.AutoCAD.ApplicationServices; 
   3:  using Autodesk.AutoCAD.DatabaseServices; 
   4:  using Autodesk.AutoCAD.Geometry; 
   5:  using Autodesk.AutoCAD.EditorInput; 
   6:   
   7:  [CommandMethod("NestedTransactions")] 
   8:  public static void NestedTransactions() 
   9:  { 
  10:      // Получаем текущий документ и базу данных 
  11:      Document acDoc = Application.DocumentManager.MdiActiveDocument; 
  12:      Database acCurDb = acDoc.Database; 
  13:   
  14:      // Создание ссылки на Менеджер Транзакций 
  15:      Autodesk.AutoCAD.DatabaseServices.TransactionManager acTransMgr; 
  16:      acTransMgr = acCurDb.TransactionManager; 
  17:   
  18:      // Создание новой транзакции 
  19:      using (Transaction acTrans1 = acTransMgr.StartTransaction()) 
  20:      { 
  21:          // Записываем текущее число активных транзакций 
  22:          acDoc.Editor.WriteMessage("\nNumber of transactions active: " + 
  23:          acTransMgr.NumberOfActiveTransactions.ToString()); 
  24:   
  25:          // Открытие таблицы Блоков для чтения 
  26:          BlockTable acBlkTbl; 
  27:          acBlkTbl = acTrans1.GetObject(acCurDb.BlockTableId, 
  28:          OpenMode.ForRead) as BlockTable; 
  29:   
  30:          // Открытие записи Таблицы Блоков Модели для записи 
  31:          BlockTableRecord acBlkTblRec; 
  32:          acBlkTblRec = acTrans1.GetObject(acBlkTbl[BlockTableRecord.ModelSpace], 
  33:          OpenMode.ForWrite) as BlockTableRecord; 
  34:   
  35:          // Создание Круга с радиусом 3 в точке 5,5 
  36:          Circle acCirc = new Circle(); 
  37:          acCirc.SetDatabaseDefaults(); 
  38:          acCirc.Center = new Point3d(5, 5, 0); 
  39:          acCirc.Radius = 3; 
  40:   
  41:          // Добавление нового объекта в Модель и транзакцию 
  42:          acBlkTblRec.AppendEntity(acCirc); 
  43:          acTrans1.AddNewlyCreatedDBObject(acCirc, true); 
  44:   
  45:          // Создание второй транзакции 
  46:          using (Transaction acTrans2 = acTransMgr.StartTransaction()) 
  47:          { 
  48:              acDoc.Editor.WriteMessage("\nNumber of transactions active: " + 
  49:              acTransMgr.NumberOfActiveTransactions.ToString()); 
  50:   
  51:              // Изменение цвета у круга 
  52:              acCirc.ColorIndex = 5; 
  53:   
  54:              // Получаем объект который будет добавлен к транзакции 1 и устанавливаем ему цвет 5 
  55:              Line acLine = new Line(new Point3d(2, 5, 0), new Point3d(10, 7, 0)); 
  56:              acLine.SetDatabaseDefaults(); 
  57:              acLine.ColorIndex = 3; 
  58:   
  59:              // Добавление нового объекта в Модель и транзакцию 
  60:              acBlkTblRec.AppendEntity(acLine); 
  61:              acTrans2.AddNewlyCreatedDBObject(acLine, true); 
  62:   
  63:              // Создание третьей транзакции 
  64:              using (Transaction acTrans3 = acTransMgr.StartTransaction()) 
  65:              { 
  66:                  acDoc.Editor.WriteMessage("\nNumber of transactions active: "     + 
  67:                  acTransMgr.NumberOfActiveTransactions.ToString()); 
  68:   
  69:                  // Изменение цвета у круга 
  70:                  acCirc.ColorIndex = 3; 
  71:   
  72:                  // Перерисовка экрана чертежа 
  73:                  acDoc.Editor.WriteMessage("\n"); 
  74:                  acDoc.Editor.Regen(); 
  75:   
  76:                  // Запрос принятия или отказа изменений в третьей транзакции 
  77:                  PromptKeywordOptions pKeyOpts = new PromptKeywordOptions(""); 
  78:                  pKeyOpts.Message = "\nKeep color change "; 
  79:                  pKeyOpts.Keywords.Add("Yes"); 
  80:                  pKeyOpts.Keywords.Add("No"); 
  81:                  pKeyOpts.Keywords.Default = "No"; 
  82:                  pKeyOpts.AllowNone = true; 
  83:   
  84:                  PromptResult pKeyRes = acDoc.Editor.GetKeywords(pKeyOpts); 
  85:   
  86:                  if (pKeyRes.StringResult == "No") 
  87:                  { 
  88:                      // Отказ изменений в 3 транзакции 
  89:                      acTrans3.Abort(); 
  90:                  } 
  91:                  else 
  92:                  { 
  93:                      // Сохранение изменений в 3 транзакции 
  94:                      acTrans3.Commit(); 
  95:                  } 
  96:   
  97:              // Высвобождение объекта транзакции 
  98:              } 
  99:   
 100:              acDoc.Editor.WriteMessage("\nNumber of transactions active: " + 
 101:              acTransMgr.NumberOfActiveTransactions.ToString());     
 102:   
 103:              // Принятие изменений во 2 транзакции 
 104:              acTrans2.Commit(); 
 105:          } 
 106:          
 107:          acDoc.Editor.WriteMessage("\nNumber of transactions active: " + 
 108:          acTransMgr.NumberOfActiveTransactions.ToString()); 
 109:   
 110:          // Принятие изменений в 1 транзакции 
 111:          acTrans1.Commit(); 
 112:      } 
 113:  }



Comments