Удаление неиспользуемых и битых Data Extraction

Автор Тема: Удаление неиспользуемых и битых Data Extraction  (Прочитано 11321 раз)

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

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Продолжая тему удаления неиспользуемого:
Как правильно удалить неиспользуемые и не найденные Data Extraction?
Database.DataLinkManager, насколько я понял, является только частью механизма.
Например, такой код превращает Data Extraction из Unreferenced в Unresolved, но не удаляет. Да и то это не всегда происходит.

Код - C# [Выбрать]
  1. [CommandMethod("rdx")]
  2. public void RemoveDataExtractions()
  3. {
  4.     Database db = HostApplicationServices.WorkingDatabase;
  5.     DataLinkManager dlm = db.DataLinkManager;
  6.     if (dlm == null)
  7.         return;
  8.  
  9.     Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  10.     int count = 0;
  11.     using (Transaction tr = db.TransactionManager.StartTransaction())
  12.     {
  13.         ed.WriteMessage("Найдено {0} dataextraction", db.DataLinkManager.DataLinkCount);
  14.  
  15.         foreach (var item in
  16.             db
  17.             .DataLinkManager
  18.             .GetDataLink().Cast<ObjectId>()
  19.             .Select(id => (DataLink)tr.GetObject(id, OpenMode.ForRead)))
  20.         {
  21.             ObjectIdCollection coll = item.GetTargets();
  22.             if (coll.Count == 0)
  23.             {
  24.                 db.DataLinkManager.RemoveDataLink(item.ObjectId);
  25.                 count++;
  26.             }
  27.         }
  28.         tr.Commit();
  29.     }
  30.  
  31.     ed.WriteMessage("\nУдалено {0} dataextraction", count);
  32. }
db.Purge() по DataLinkDictionaryId тоже даёт неправильные результаты.
Алексей

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

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

Отмечено как Решение Александр Ривилис 25-05-2016, 13:15:47

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Файла не дождался. Поэтому экспериментировал сам. Попробуй такой код:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7. using AcRx = Autodesk.AutoCAD.Runtime;
  8. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  9. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  10. using AcGe = Autodesk.AutoCAD.Geometry;
  11. using AcEd = Autodesk.AutoCAD.EditorInput;
  12.  
  13. [assembly: CommandClass(typeof(TestUnref.MyCommands))]
  14.  
  15. namespace TestUnref
  16. {
  17.   public class MyCommands
  18.   {
  19.     // Печатаем имена не используемых/не найденных DataLink
  20.     // и удаляем их
  21.     [CommandMethod("TestUnrefDlink")]
  22.     public void TestUnrefDlink()
  23.     {
  24.       AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument;
  25.       AcDb.Database db = doc.Database;
  26.       AcEd.Editor ed = doc.Editor;
  27.       AcDb.ObjectIdCollection ids = new AcDb.ObjectIdCollection();
  28.       // Имена DataLink
  29.       ed.WriteMessage("\nНе используемые/не найденные DataLink: ");
  30.       AcDb.ObjectId idLinkDict = db.DataLinkDictionaryId;
  31.       if (!idLinkDict.IsNull) {
  32.         using (AcDb.DBDictionary dLinkDict = db.DataLinkDictionaryId.Open(OpenMode.ForRead) as AcDb.DBDictionary) {
  33.           foreach (AcDb.DBDictionaryEntry ent in dLinkDict) ids.Add(ent.Value);
  34.         }
  35.         foreach (AcDb.ObjectId id in ids) {
  36.           using (AcDb.DataLink dLink = id.Open(OpenMode.ForRead) as AcDb.DataLink) {
  37.             bool bIsValid = true;
  38.             if (!dLink.IsValid) {
  39.               bIsValid = false;
  40.             } else {
  41.               bIsValid = false;
  42.               foreach (AcDb.ObjectId id_target in dLink.GetTargets()) {
  43.                 if (id_target.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(AcDb.Table)))) {
  44.                   bIsValid = true;
  45.                   break;
  46.                 }
  47.               }
  48.             }
  49.             if (!bIsValid) {
  50.               ed.WriteMessage("\n\tИмя={0} Связь={1}", dLink.Name, dLink.ConnectionString);
  51.               dLink.UpgradeOpen();
  52.               dLink.Erase(); // Удаляем его
  53.             }
  54.           }
  55.         }
  56.       }
  57.     }
  58.   }
  59. }
  60.  

P.S.: Добавил обработку не найденных DataLink-ов.
« Последнее редактирование: 08-09-2014, 23:00:58 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Александр Наумович, прошу прощения, что не успел выложить файл.
Идея понятна - и отрабатывает прекрасно (я переделал под себя).
Спасибо!
Алексей

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

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

Оффлайн bargoolАвтор темы

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
Согласен.
Там есть мои "библиотечные" методы расширения, но на понимание происходящего они не влияют. По-этому не буду перегонять в стандартные варианты
Код - C# [Выбрать]
  1. [CommandMethod("rdx")]
  2. public void RemoveUnusedDataExtractions()
  3. {
  4.     Database db = HostApplicationServices.WorkingDatabase;
  5.     Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
  6.  
  7.     ed.WriteLine("Удаляем неиспользуемые/ненайденные DataExtraction: ");
  8.     ObjectId linkDictId = db.DataLinkDictionaryId;
  9.     if (linkDictId.IsNull || !linkDictId.IsValid)
  10.     {
  11.         ed.WriteLine("Ошибка получения словаря DataExtraction!");
  12.         return;
  13.     }
  14.  
  15.     int deletedCount = 0;
  16.  
  17.     using (Transaction tr = db.TransactionManager.StartTransaction())
  18.     {
  19.         DBDictionary dataLinkDict = linkDictId.GetObject<DBDictionary>(OpenMode.ForRead);
  20.  
  21.         RXClass tableClass = RXClass.GetClass(typeof(Table));
  22.  
  23.         foreach (DBDictionaryEntry entry in dataLinkDict)
  24.         {
  25.             ObjectId dataLinkId = entry.Value;
  26.             if (!dataLinkId.IsValid || dataLinkId.IsNull || dataLinkId.IsEffectivelyErased)
  27.                 continue;
  28.  
  29.             DataLink dataLink = dataLinkId.GetObject<DataLink>(OpenMode.ForRead);
  30.                    
  31.             bool isDataLinkValid = dataLink.IsValid &&
  32.                 dataLink
  33.                 .GetTargets().Cast<ObjectId>()
  34.                 .Any(idTarget => idTarget.ObjectClass.IsDerivedFrom(tableClass));
  35.  
  36.             if (!isDataLinkValid)
  37.             {
  38.                 ed.WriteLine("{0}: Имя = {1}; Связь = {2}", ++deletedCount, dataLink.Name, dataLink.ConnectionString);
  39.                 dataLink.UpgradeOpen();
  40.                 dataLink.Erase();
  41.             }
  42.         }
  43.  
  44.         ed.WriteLine("Удалено: {0} DataExtraction", deletedCount);
  45.         tr.Commit();
  46.     }
  47. }
Алексей

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Я немного подумал и решил, что правильнее заменить
Код - C# [Выбрать]
  1. RXClass tableClass = RXClass.GetClass(typeof(Table));
на
Код - C# [Выбрать]
  1. RXClass tableClass = RXClass.GetClass(typeof(Entity));
На будущее - вдруг DataLink будет использоваться не только для Table.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн undertaker1984

  • ADN OPEN
  • Сообщений: 1
  • Карма: 0
Код - vb.net [Выбрать]
  1. [Public Sub Sub_lab_ExlLinkDeleteEmpty()
  2.         Dim AcDoc As Document = Application.DocumentManager.MdiActiveDocument
  3.         Dim AcDb As Database = AcDoc.Database
  4.         Dim AcEdtr As Editor = AcDoc.Editor
  5.         Dim AcObjIds As New ObjectIdCollection
  6.         Dim AcLinkId As ObjectId = AcDb.DataLinkDictionaryId
  7.         AcEdtr.WriteMessage(vbLf & "Не используемые/не найденные DataLink: ")
  8.         If AcLinkId.IsNull = False Then
  9.             Using acTrans As Transaction = AcDb.TransactionManager.StartTransaction()
  10.                 Using AcDbDict As DBDictionary = DirectCast(acTrans.GetObject(AcLinkId, OpenMode.ForRead), DBDictionary)
  11.                     For Each AcDbDictEnt As DBDictionaryEntry In AcDbDict
  12.                         AcObjIds.Add(AcDbDictEnt.Value)
  13.                     Next
  14.                     For Each id As ObjectId In AcObjIds
  15.                         Using dLink As DataLink = DirectCast(acTrans.GetObject(id, OpenMode.ForRead), DataLink)
  16.                             Dim bIsValid As Boolean = True
  17.                             If Not (dLink.IsValid) Then
  18.                                 bIsValid = False
  19.                             Else
  20.                                 bIsValid = False
  21.                                 For Each id_target As ObjectId In dLink.GetTargets
  22.                                     If id_target.ObjectClass.IsDerivedFrom(RXClass.GetClass(GetType(Entity))) Then
  23.                                         bIsValid = True
  24.                                         Exit For
  25.                                     End If
  26.                                 Next
  27.                             End If
  28.                             If Not (bIsValid) Then
  29.                                 AcEdtr.WriteMessage(vbLf & "Имя={0} Связь={1}", dLink.Name, dLink.ConnectionString)
  30.                                 dLink.UpgradeOpen()
  31.                                 dLink.Erase()
  32.                             End If
  33.                         End Using
  34.                     Next
  35.                 End Using
  36.                 acTrans.Commit()
  37.             End Using
  38.         End If
  39.     End Sub]
  40.  
  41.  
« Последнее редактирование: 04-05-2023, 11:44:18 от undertaker1984 »