Программная очистка файла в NC 23-23.1

Столкнулся со странной работой стандартного PurgeAll в файлах с внешними ссылками. Если во внешней ссылке есть линии с пользовательскими типами линий, можно словить очень странный баг.

Выполняю достаточно несложный код (одно "но" - все это приходится делать внутри отдельной транзакции, поскольку помимо очистки делается еще масса телодвижений)

1
2
3
4
5
nanoCAD.Document comDoc = doc.AcadDocument as nanoCAD.Document;
for (int i = 0; i < 3; i++)
{
    comDoc.PurgeAll();
}

И вроде бы все хорошо. Пока не будет выполнена регенерация. После нее все линии во внешних ссылках могут преобразоваться (визуально) в Continuous. Спасает только ручная перезагрузка ссылки. Но пользователям-то это не объяснишь!

Пришлось обращаться на форум разработчиков, где Андрей Лысенко и показал решение. Процитирую его:

Одашники (DwgDirect) полтора года назад поправили в своих потрохах поправили purge(OdDbObjectIdArray)
<...>
У нас это вошло в версию 24.0

С его любезного разрешения привожу слегка переделанный вариант его решения, хотя проблема в версиях 24 и более поздних, похоже, решена.

Прежде всего два служебных метода:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void PurgeAddDictRecords(DBDictionary dict, ObjectIdCollection ids)
{
    foreach (DBDictionaryEntry entry in dict)
    {
        ObjectId objId = entry.Value;

        if (objId.Database == dict.Database)
            ids.Add(objId);
    }
}

private static void PurgeAddTableRecords(SymbolTable symbolTable, ObjectIdCollection ids)
{
    foreach (ObjectId objId in symbolTable)
    {

        if (objId.Database == symbolTable.Database)
            ids.Add(objId);
    }
}

В принципе, все достаточно прозрачно: очистка словарей (типа словаря табличных стилей, мультилиний и т.п.), и очистка символьных таблиц.

Ну и основная команда:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
[CommandMethod("purge-sample")]
public static void PurgeAlCommand()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    if (doc == null)
    {
        return;
    }

    Database dbase = doc.Database;
    using (Transaction trans = dbase.TransactionManager.StartTransaction())
    {
        for (int i = 0; i < 3; i++)
        {
            ObjectIdCollection idCollection = new ObjectIdCollection();

            PurgeAddDictRecords((DBDictionary) dbase.TableStyleDictionaryId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddDictRecords((DBDictionary) dbase.MLStyleDictionaryId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddDictRecords((DBDictionary) dbase.MLeaderStyleDictionaryId.GetObject(OpenMode.ForRead), idCollection);

            PurgeAddTableRecords((SymbolTable)dbase.BlockTableId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddTableRecords((SymbolTable)dbase.DimStyleTableId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddTableRecords((SymbolTable)dbase.LayerTableId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddTableRecords((SymbolTable)dbase.LinetypeTableId.GetObject(OpenMode.ForRead), idCollection);
            PurgeAddTableRecords((SymbolTable)dbase.TextStyleTableId.GetObject(OpenMode.ForRead), idCollection);

            dbase.Purge(idCollection);
            foreach (ObjectId objectId in idCollection)
            {
                DBObject dbObj = objectId.GetObject(OpenMode.ForWrite);
                dbObj.Erase();
            }
        }

        trans.Commit();
    }
}

Да, для версии 24 и более поздних (повторюсь!) скорее всего, это уже не понадобится. Но сайт-то шпаргалка! ;)

Размещено в .NET, nanoCAD · Метки: , , ,



Поделитесь своим мнением


Я не робот.