Не работает добавление труб в сеть, открытую без транзакции

Автор Тема: Не работает добавление труб в сеть, открытую без транзакции  (Прочитано 7525 раз)

0 Пользователей и 3 Гостей просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Это скорее не вопрос, а констатация факта. Но есть шанс, что я что-то упускаю. В общем, ситуация такая: если сеть открыта без транзакции, то метод AddLinePipe вызывает исключение:
  ************** Текст исключения **************
Autodesk.AutoCAD.Runtime.Exception: Fail to add line pipe.
   в Autodesk.Civil.Checker.Check(ErrorStatus es, String message)
   в Autodesk.Civil.DatabaseServices.Network.AddLinePipe(ObjectId pipeFamilyId, ObjectId pipeSizeId, LineSegment3d line, ObjectId& newPipeId, Boolean applyRules)
   в CreateNetworkTest.CmdClass.AddPipe(Network net, ObjectId pipeFamId, ObjectId pipeSizeId) в D:\Work\Tests\_C3d\CreateNetworkTest\CreateNetworkTest\CmdClass.cs:строка 59
   в CreateNetworkTest.CmdClass.CreateNetCmd() в D:\Work\Tests\_C3d\CreateNetworkTest\CreateNetworkTest\CmdClass.cs:строка 50
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
   в Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
Проверял в версиях 2016-2019.
Код для теста:
Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.DatabaseServices;
  2. using Autodesk.AutoCAD.Geometry;
  3. using Autodesk.AutoCAD.Runtime;
  4. using Autodesk.Civil.ApplicationServices;
  5. using Autodesk.Civil.DatabaseServices;
  6. using Autodesk.Civil.DatabaseServices.Styles;
  7.  
  8. #pragma warning disable 0618
  9.  
  10. namespace CreateNetworkTest
  11. {
  12.     public class CmdClass
  13.     {
  14.         /// <summary>
  15.         /// Этот метод работает
  16.         /// </summary>
  17.         [CommandMethod("CreateNetworkTestTrans")]
  18.         public void CreateNetCmdTrans()
  19.         {
  20.             CreateNetAndGetParamsForPipe
  21.                 (out ObjectId netId,
  22.                 out ObjectId pipeFamId,
  23.                 out ObjectId pipeSizeId);
  24.  
  25.             // Добавляем трубу в сеть, открытую с помощью транзакции
  26.             using (Transaction tr = netId.Database.TransactionManager.StartTransaction())
  27.             {
  28.                 Network net = tr.GetObject(netId, OpenMode.ForWrite) as Network;
  29.  
  30.                 AddPipe(net, pipeFamId, pipeSizeId);
  31.  
  32.                 tr.Commit();
  33.             }            
  34.         }
  35.  
  36.         /// <summary>
  37.         /// Этот метод не работает
  38.         /// </summary>
  39.         [CommandMethod("CreateNetworkTestNoTrans")]
  40.         public void CreateNetCmdNoTrans()
  41.         {
  42.             CreateNetAndGetParamsForPipe
  43.                 (out ObjectId netId,
  44.                 out ObjectId pipeFamId,
  45.                 out ObjectId pipeSizeId);
  46.  
  47.             // Добавляем трубу в сеть, открытую без транзакции
  48.             using (Network net = netId.Open(OpenMode.ForWrite) as Network)
  49.             {
  50.                 AddPipe(net, pipeFamId, pipeSizeId);
  51.             }
  52.         }
  53.  
  54.         static void AddPipe(Network net, ObjectId pipeFamId, ObjectId pipeSizeId)
  55.         {
  56.             LineSegment3d line = new LineSegment3d
  57.                 (new Point3d(0, 0, 0), new Point3d(100, 0, 0));
  58.             ObjectId pipeId = ObjectId.Null;
  59.             net.AddLinePipe
  60.                 (pipeFamId, pipeSizeId, line, ref pipeId, false);
  61.         }
  62.  
  63.         static void CreateNetAndGetParamsForPipe
  64.             (out ObjectId netId, out ObjectId pipeFamId,
  65.             out ObjectId pipeSizeId)
  66.         {
  67.             CivilDocument cdoc = CivilApplication.ActiveDocument;
  68.             string newNetName = "NewNetwork";
  69.             netId = Network.Create(cdoc, ref newNetName);
  70.  
  71.             ObjectId partsListId = cdoc.Styles.PartsListSet[0];
  72.             using (Network net
  73.                 = netId.Open(OpenMode.ForWrite) as Network)
  74.             {
  75.                 net.PartsListId = partsListId;
  76.             }            
  77.  
  78.             using (PartsList partsList
  79.                 = partsListId.Open(OpenMode.ForRead) as PartsList)
  80.             {
  81.                 ObjectIdCollection pipeFamIds
  82.                     = partsList.GetPartFamilyIdsByDomain(DomainType.Pipe);
  83.                 pipeFamId = pipeFamIds[0];
  84.             }            
  85.  
  86.             using (PartFamily pipeFam
  87.                 = pipeFamId.Open(OpenMode.ForRead) as PartFamily)
  88.             {
  89.                 pipeSizeId = pipeFam[0];
  90.             }                      
  91.         }
  92.     }
  93. }
  94.  

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А если в 48 строке заменить
Код - C# [Выбрать]
  1. using (Network net = netId.Open(OpenMode.ForWrite) as Network)
на
Код - C# [Выбрать]
  1. using (Network net = netId.Open(OpenMode.ForRead) as Network)
?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А вообще подозреваю, что неважно каким методом открыта Network для вызова AddLinePipe. Важно, что в этот момент должна быть открыта хоть какая-нибудь транзакция.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Фатал
Так. Это правильно. :) А добавить внешнюю (обычную) транзакцию?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Вы имеете в виду вот так?:
Код - C# [Выбрать]
  1. [CommandMethod("CreateNetworkTestNoTrans")]
  2. public void CreateNetCmdNoTrans()
  3. {
  4.     CreateNetAndGetParamsForPipe
  5.         (out ObjectId netId,
  6.         out ObjectId pipeFamId,
  7.         out ObjectId pipeSizeId);
  8.  
  9.     using (Transaction tr = netId.Database.TransactionManager.StartTransaction())
  10.     {
  11.         // Добавляем трубу в сеть, открытую без транзакции
  12.         using (Network net = netId.Open(OpenMode.ForWrite) as Network)
  13.         {
  14.             AddPipe(net, pipeFamId, pipeSizeId);
  15.         }
  16.  
  17.         tr.Commit();
  18.     }
  19. }
  20.  
А вот так - работает! Шикарно :)

Отмечено как Решение Дмитрий Загорулькин 27-06-2018, 23:08:59

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Вы имеете в виду вот так?:
Именно. Я заподозрил, что там в коде они используют нечто ObjectId.GetObject(...), что требует наличие активной транзакции...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
А там вообще вызов Native-метода:
Код - C# [Выбрать]
  1. ...
  2.  
  3. AeccNetworkErrorCode aeccNetworkErrorCode;
  4. global::<Module>.AeccDbNetwork.addLinePipe((AeccDbNetwork*)impObj, &aeccNetworkErrorCode, ptr2, &acDbObjectId, &acGePoint3d, &acGePoint3d2, &?kNull@AcDbObjectId@@2V1@B, applyRules);
  5. global::<Module>.Autodesk.Civil.Checker.Check((Acad.ErrorStatus)(*(int*)(&aeccNetworkErrorCode)), "Fail to add line pipe.");
  6. ObjectId val3 = newPipeId = global::<Module>.ToObjectId(&?kNull@AcDbObjectId@@2V1@B);
  7.  
  8. ...
  9.  

Код - C# [Выбрать]
  1. [DllImport("", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
  2. [MethodImpl(MethodImplOptions.Unmanaged)]
  3. [SuppressUnmanagedCodeSecurity]
  4. internal unsafe static extern AeccNetworkErrorCode* AeccDbNetwork.addLinePipe(AeccDbNetwork* P_0, AeccNetworkErrorCode* P_1, AecRmCString* P_2, AcDbObjectId* P_3, AcGePoint3d* P_4, AcGePoint3d* P_5, AcDbObjectId* P_6, [MarshalAs(UnmanagedType.U1)] bool P_7);

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
А там вообще вызов Native-метода:
Ну транзакции, как ты догадываешься, не только для managed, но и для native.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
как ты догадываешься
Вы слишком хорошего обо мне мнения - даже не подозревал :)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
как ты догадываешься
Вы слишком хорошего обо мне мнения - даже не подозревал :)
А ты глянь что такое Transaction и TransactionManager.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дмитрий ЗагорулькинАвтор темы

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Transaction: This .NET class wraps the AcTransaction ObjectARX class.
TransactionManager: This .NET class wraps the AcDbTransactionManager ObjectARX class.

Да, это чисто ObjectARX объекты. Это для меня новость! То ли не знал, то ли уже забыл. В первом случае: "Век живи - век учись", во втором: "Повторение - мать ученья"  :D