Поиск объектов в сценарии

Примечание
Перед началом работы со сценариями рекомендуется ознакомиться со стандартами написания программного кода на языке C#.

Наиболее частая операция в сценариях - это поиск каких-то объектов в системе по различным условиям. В системе ELMA поиск осуществляется с помощью методов Find или FindAll менеджера объекта

Использование фильтров

Наиболее эффективный метод поиска – это использование фильтров. Фильтры настраиваются при создании или редактировании объекта в Дизайнере:

и в каждом свойстве нужно указать, нужно ли по нему фильтровать в дальнейшем:

После того, как все настройки сделаны и модель опубликована, можно использовать фильтры в сценариях:

C# Code
//Получаем менеджер для объекта Питомец
var manager = EntityManager<Pitomec>.Instance;

//Создаем фильтр для объекта Питомец
var filter = new PitomecFilter()
{
    Vozrast = new EleWise.ELMA.Model.Ranges.Int64Range()
    {
        From = 5
    },
    Vid = new DropDownItem("Кошка")
};

//Получаем результирующий список объектов по фильтру
var pets = manager.Find(filter);

Фильтр представляет собой специальный класс, который располагается в том же пространстве имен, что и класс объекта, и имя его получается из имени класса объекта с постфиксом Filter (т.е. для класса Pitomec у нас создается класс фильтра PitomecFilter).

При поиске при помощи фильтра, отбор производится по равенству значения в фильтре и в базе, если нет иных настроек (например для переменной типа Целое число можно указать, что фильтровать надо по диапазону, а не по равенству). Для переменной типа Строка фильтрация производится по совпадению подстроки (без учета регистра). Фильтрацию можно проводить по всем типам переменных.

 

Для системных объектов вы не можете изменить настройки фильтрации переменных

Использование фильтров при поиске достаточно просто и позволяет вам искать нужные, однако тут вы можете столкнуться с ограничением настроек фильтров и необходимостью искать по полям не включенным в фильтрацию, далее показан простой способ, как это сделать.

Поиск по явному совпадению с использованием LINQ

В языке C# 3.0 и выше появились очень полезные конструкции называемые "лямбда-выражения" которые мы можем использовать для поиска объектов.

 

C# Code
var pets = EntityManager<Pitomec>.Instance.Find(p => p.Hozyain == context.Kontakt && p.Imya == "Шарик");

В примере выше мы используем выражение p => p.Hozyain == context.Kontakt && p.Imya == "Шарик" для фильтрации. Согласно этому выражению мы должны найти все объекты типа Питомец у которых Хозяин равен значению переменной Контакт из контекста И Имя равно (полностью совпадает с) "Шарик".

При использовании лямбда-выражений вам уже не нужно думать про настройки фильтра объекта, вы можете искать по любому объекту и с использованием любого свойства этого объекта.

 

При поиске с использованием лямбда выражений есть ряд ограничений на само выражение:
  • выражение может содержать только логические операторы И (&&) или ИЛИ (||) в любом сочетании;
  • выражение может искать только по равенству переменной и значения (==);
  • в выражении нельзя искать по вложенным полям для объектов;
  • в выражении нельзя использовать функции применимо к левому операнду - переменной.

Чтобы стало понятнее поясним на примерах, какие выражения являются правильными а какие - нет и почему.

 

Правильные выражения
EntityManager<Pitomec>.Instance.Find(p => p.Hozyain == context.Kontakt && p.Imya == pName//Тут pName - это локальная переменная типа String
EntityManager<Pitomec>.Instance.Find(p => p.Vozrast == 10 || p.Vid == new DropDownItem("Кошка")) //Сравнение идет только с конечными данными
Неправильные выражения
EntityManager<Pitomec>.Instance.Find(p => p.Vozrast > 10) //Нельзя использовать оператор сравнения "больше"
EntityManager<Pitomec>.Instance.Find(p => p.Imya == p.Hozyain.Name) //Нельзя использовать переменные искомого объекта справа и слева от оператора сравнения
EntityManager<Pitomec>.Instance.Find(p => p.Hozyain.Name == "Иван") //Нельзя искать по вложенным полям объектов

Как видите использование лямбда-выражений вместе с дополнительными возможностями привносит и значительные ограничения, но вы можете использовать их независимо от настроек объекта. 

Если же вам необходима более гибкая и продвинутая система поиска, вы можете воспользоваться поиском с использованием встроенного языка EQL.

Поиск с использованием встроенного языка EQL

Каждый фильтр в системе наследует базовый интерфейс IFilter в котором обязательно есть строковое поле Query. Используя в этом поле запрос на языке EQL, можно выбрать объекты по достаточно гибкому условию.

 

C# Code
//Получаем менеджер для объекта Питомец
var manager = EntityManager<Pitomec>.Instance;

//Создаем базовый фильтр и заполняем поле запроса
var filter = new Filter()
{
    Query = "(Vid IS NULL OR Vozrast > 25) AND Hozyain IN (Name = ’Иван’)"
}

//Получаем результирующий список объектов по фильтру
var pets = manager.Find(filter);

В этом примере мы ищем все объекты типа Питомец для которых справедливо, что Вид имеет пустое значение ИЛИ Возраст больше 25 И Хозяин удовлетворяет условию, что Имя равно "Иван". Давайте разберем по частям:

  • Вид имеет пустое значение ИЛИ Возраст больше 25 - это выражение описывается как Vid IS NULL OR Vozrast > 25;
  • Хозяин удовлетворяет условию, что Имя равно "Иван" - это выражение описывается как Hozyain IN (Name = ’Иван’).
При использовании языка EQL можно формировать подзапросы и делать дополнительную фильтрацию по вложенным полям объектов

Вы можете найти очень много применений для данного варианта поиска. Запросы на языке EQL очень гибки и позволяют выбирать практически по любому условию. Вам стоит выбрать именно этот метод поиска, если другие два не подходят по каким-либо причинам.

Дополнительные материалы