Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: alihovsky от 23-10-2019, 18:11:22

Название: Назначение слоя в цикле
Отправлено: alihovsky от 23-10-2019, 18:11:22
  Приветствую всех. Совсем недавно начал изучать C#. Конечно сразу запнулся на трансакциях. Код должен назначить выбранным объектом слой.  Понимаю, что нужно правильно выйти из трансакции. Похожий вопрос был на сайте, но что то без решения((. Помогите новичку, где тут ошибка?




Код - C# [Выбрать]
  1.      public void SelObjOnscr()
  2.     {
  3.         Document acDoc = Application.DocumentManager.MdiActiveDocument;
  4.         Database acCurDb = acDoc.Database;
  5.         PromptSelectionResult acSSPrompt = acDoc.Editor.GetSelection();
  6.         if (acSSPrompt.Status == PromptStatus.OK)
  7.         {
  8.             using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
  9.             {
  10.                 {
  11.                     LayerTable acLyrTbl;
  12.                     acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
  13.                                                     OpenMode.ForRead) as LayerTable;
  14.                     string sLayerName = "mylayer";
  15.                     if (acLyrTbl.Has(sLayerName) == false)
  16.                     {
  17.                         using (LayerTableRecord acLyrTblRec = new LayerTableRecord())
  18.                         {
  19.                             acLyrTblRec.Name = sLayerName;
  20.                             acLyrTbl.UpgradeOpen();
  21.                             acLyrTbl.Add(acLyrTblRec);
  22.                         }
  23.                     }
  24.                     SelectionSet acSSet = acSSPrompt.Value;
  25.                     foreach (SelectedObject acSSObj in acSSet)
  26.                     {
  27.                         if (acSSObj != null)
  28.                         {
  29.                             Entity acEnt = acTrans.GetObject(acSSObj.ObjectId,
  30.                                                                 OpenMode.ForWrite) as Entity;
  31.                             if (acEnt != null)
  32.                             {
  33.                                 acEnt.Layer = sLayerName;
  34.                             }
  35.                         }
  36.                     }
  37.                 }
  38.                 acTrans.Commit();
  39.             }
  40.         }
  41.     }  
 
Название: Re: Назначение слоя в цикле
Отправлено: avc от 23-10-2019, 18:35:19
У вас объекты, только что полученные из чертежа, опять заталкиваются в модель и в транзакцию. Сохранять в БД надо только новые объекты, у которых Id.IsNull Просто уберите AppendEntity и AddNewlyCreatedDBObject.
BTR модели вам не нужен.
И еще. Нет смысла открывать транзакцию пока не выбраны объекты. Вызывайте запрос GetSelection до открытия транзакции.
Название: Re: Назначение слоя в цикле
Отправлено: alihovsky от 24-10-2019, 06:53:27
Спасибо. Только не совсем понял, почему в строке

acLyrTbl = acTrans.GetObject(acCurDb.LayerTableId,
                                                    OpenMode.ForRead) as LayerTable

"OpenMode.ForRead", а не "OpenMode.ForWrite". "ForRead" копировал из документации, но код срабатывает при обоих вариантах, это фича VS?
Название: Re: Назначение слоя в цикле
Отправлено: Александр Ривилис от 24-10-2019, 08:37:12
alihovsky,
Потому, что потом ты вызываешь acLyrTbl.UpgradeOpen(); для перевода в состояние OpenMode.ForWrite
Название: Re: Назначение слоя в цикле
Отправлено: alihovsky от 24-10-2019, 09:04:19
Потому, что потом ты вызываешь acLyrTbl.UpgradeOpen(); для перевода в состояние OpenMode.ForWrite

Вроде дошло) , спасибо
Название: Re: Назначение слоя в цикле
Отправлено: avc от 24-10-2019, 10:32:43
И не так давно обсуждалось, что UpgradeOpen не всегда корректно работает с транзакциями. Нынче модно вместо него вызывать еще раз GetObject, но уже для записи. Результат такого вызова можно никуда не сохранять - состояние объекта и так изменится.
Код - C# [Выбрать]
  1.        {
  2.         acLyrTblRec.Name = sLayerName;
  3.         acTrans.GetObject(acCurDb.LayerTableId,  OpenMode.ForWrite);
  4.         acLyrTbl.Add(acLyrTblRec);
  5.        }