Здравствуйте!
Сделал метод для поиска объектов внутри БД чертежа:
/// <summary>
/// Find a object in the database
/// </summary>
/// <typeparam name="T">Type of the object</typeparam>
/// <param name="db">Database of the drawing</param>
/// <param name="testFunction">Test function for identification of the object</param>
/// <returns>ObjectId or ObjectId.Null if object is not found</returns>
public static ObjectId FindObjectInDatabase<T>
(this Database db, Func<T, bool> testFunction) where T : DBObject
{
Handle handseed = db.Handseed;
long handseedTotal = handseed.Value;
for (int i = 1; i < handseedTotal; i++)
{
ObjectId currentId = db.IdFromHandleValue(i);
if (!CheckObjectIdFor<T>(currentId)) continue;
using (T obj = currentId.SafeOpen<T>())
{
if (testFunction(obj)) return currentId;
}
}
return ObjectId.Null;
}
Сделал команду, которая использует этот метод, чтобы найти нужный объект. Запустил. И уже несколько десятков минут жду результат. Остановил, посмотрел промежуточные значения:
handseedTotal = 169059859,
i = 23987369
Посмотрел, какие объекты обрабатываются. Все получаемые currentId - Null. То есть, Handseed имеет большое значение, но до него десятки (сотни?) миллионов номеров не ссылаются на объекты! Получается, что такой метод поиска объектов в базе в таких случаях неоптимален? Или есть какой-то фокус, позволяющий быстро пропускать "пустые" участки номеров?
Вспомогательные методы:
/// <summary>
/// Восстановление идентификатора объекта из его
/// числового значения хендла
/// </summary>
/// <param name="db">База данных чертежа</param>
/// <param name="value">Числовое значение хендла</param>
/// <returns>Идентификатор объекта или ObjectId.Null при неудаче</returns>
public static ObjectId IdFromHandleValue(this Database db, long value)
=> IdFromHandle(db, new Handle(value));
/// <summary>
/// Get ObjectId from the handle of the database object
/// </summary>
/// <param name="db">Database of the drawing</param>
/// <param name="handle">Handle of the object</param>
/// <returns>ObjectId value or ObjectId.Null</returns>
public static ObjectId IdFromHandle(this Database db, Handle handle)
{
ObjectId ret = ObjectId.Null;
db?.TryGetObjectId(handle, out ret);
return ret;
}
/// <summary>
/// Проверка типа Id объекта
/// </summary>
/// <typeparam name="T">Тип, на который проверяем</typeparam>
/// <param name="id">Id объекта</param>
/// <param name="allowErased">Допускается объект, который был удален</param>
/// <returns></returns>
public static bool CheckObjectIdFor<T>
(this ObjectId id,
bool allowErased = false) where T : DBObject
{
RXClass forCheck = RXObject.GetClass(typeof(T));
return !id.IsNull
&& id.IsValid
&& (allowErased || (!id.IsErased && !id.IsEffectivelyErased))
&& (id.ObjectClass.Equals(forCheck) || id.ObjectClass.IsDerivedFrom(forCheck));
}