работа с хайлоад блоками
use Bitrix\Highloadblock as HL;
use Bitrix\Main\Entity;
CModule::IncludeModule("highloadblock");
найти ID HLBlock'а с названием $code
$hlbl = HL\HighloadBlockTable::getList([
    'filter' => ['=NAME' => $code]
])->fetch()["ID"];
получить entity и dataclass
$hlbl = 1;
$hlblock = HL\HighloadBlockTable::getById($hlbl)->fetch(); 
$entity = HL\HighloadBlockTable::compileEntity($hlblock); 
$entity_data_class = $entity->getDataClass();
выборка из HlBlock'а
$result = $entity_data_class::getList([
  'select'  => ... // имена полей, которые необходимо получить в результате
  'filter'  => ... // описание фильтра для WHERE и HAVING
  'group'   => ... // явное указание полей, по которым нужно группировать результат
  'order'   => ... // параметры сортировки
  'limit'   => ... // количество записей
  'offset'  => ... // смещение для limit
  'runtime' => ... // динамически определенные поля
  'cache'   => ['ttl'=>3600] // кеширование выборки
]);
while ($row = $result->fetch())
{
    $rows[] = $row;
}
// для всех записей
$rows = $result->fetchAll();
filter со сложной логикой
// WHERE ID = 1 AND ISBN = '9780321127426'
BookTable::getList(array(
    'filter' => array(
        '=ID' => 1,
        '=ISBN' => '9780321127426'
    )
));
// WHERE (ID=1 AND ISBN='9780321127426') OR (ID=2 AND ISBN='9781449314286')
BookTable::getList(array(
    'filter' => array(
        'LOGIC' => 'OR',
        array(
            // 'LOGIC' => 'AND', // по умолчанию элементы склеиваются через AND
            '=ID' => 1,
            '=ISBN' => '9780321127426'
        ),
        array(
            '=ID' => 2,
            '=ISBN' => '9781449314286'
        )
    )
));
Полный список операторов сравнения, которые можно использовать в фильтре:
= равно (работает и с массивами)
% подстрока
> больше
< меньше
@ IN (EXPR), в качестве значения передается объект DB\SqlExpression
!@ NOT IN (EXPR), в качестве значения передается объект DB\SqlExpression
!= не равно
!% не подстрока
>< между, в качестве значения передается массив array(MIN, MAX)
>= больше или равно
<= меньше или равно
=% LIKE
%= LIKE
== булевое выражение для ExpressionField (например, для EXISTS() или NOT EXISTS())
!>< не между, в качестве значения передается массив array(MIN, MAX)
!=% NOT LIKE
!%= NOT LIKE
'==ID' => null строгое сравнение с NULL по ID
'!==NAME' => null строгое сравнение с NULL по NAME
offset/limit
// 10 последних записей
BookTable::getList(array(
    'order' => array('ID' => 'DESC')
    'limit' => 10
));
// 5-я страница с записями, по 20 на страницу
BookTable::getList(array(
    'order' => array('ID')
    'limit' => 20,
    'offset' => 80
));
runtime
// подсчет количества записей в сущности
BookTable::getList(array(
    'select' => array('CNT'),
    'runtime' => array(
        new Entity\ExpressionField('CNT', 'COUNT(*)')
    )
));
// SELECT COUNT(*) AS CNT FROM my_book
// Если вычисляемое поле необходимо только в секции `select` (как это чаще всего бывает),
// то секцию `runtime` использовать необязательно: можно сэкономить время,
//поместив выражение сразу в `select`
BookTable::getList(array(
    'select' => array(
        new Entity\ExpressionField('MAX_AGE', 'MAX(%s)', array('AGE_DAYS'))
    )
));
// SELECT MAX(DATEDIFF(NOW(), PUBLISH_DATE)) AS MAX_AGE FROM my_book
Сброс кеша происходит в любом методе add/update/delete. Принудительный сброс кеша для таблицы:
\Bitrix\Main\UserTable::getEntity()->cleanCache();
В дополнении к GetList существует еще ряд методов, которые позволяют в более короткой форме получить определенные данные
BookTable::getById(1);
BookTable::getByPrimary(array('ID' => 1));
// такие вызовы будут аналогичны следующему вызову getList:
BookTable::getList(array(
    'filter' => array('=ID' => 1)
));
// getRowById($id) - производит выборку по первичному ключу, но возвращается массив данных;
$row = BookTable::getRowById($id);
// аналогичный результат можно получить так:
$result = BookTable::getById($id);
$row = $result->fetch();
// или так
$result = BookTable::getList(array(
    'filter' => array('=ID' => $id)
));
$row = $result->fetch();
// getRow(array $parameters) - производит выборку не по первичному ключу,
// а по каким-то другим параметрам. При этом возвращается только одна запись
$row = BookTable::getRow(array(
    'filter' => array('%=TITLE' => 'Patterns%'),
    'order' => array('ID')
));
// аналогичный результат можно получить так:
$result = BookTable::getList(array(
    'filter' => array('%=TITLE' => 'Patterns%'),
    'order' => array('ID')
    'limit' => 1
));
$row = $result->fetch();
формирование запроса с помощью объекат Entity\Query
// получение данных через getList
$result = BookTable::getList(array(
    'select' => array('ISBN', 'TITLE', 'PUBLISH_DATE')
    'filter' => array('=ID' => 1)
));
// аналогично через Entity\Query
$q = new Entity\Query(BookTable::getEntity());
$q->setSelect(array('ISBN', 'TITLE', 'PUBLISH_DATE'));
$q->setFilter(array('=ID' => 1));
$result = $q->exec();
пример массива с данными
$data = [
"UF_DATE_FROM"=>'$datefrom',
"UF_DATE_TO"=>'$dateto',
];
добавление данных
$result = $entity_data_class::add($data);
$ID = $result->getId();
изменение элемента
$result = $entity_data_class::update($ID, $data);
if (!$result->isSuccess()) {
    // обработка ошибки
}
удаление элемента
$result = $entity_data_class::delete($ID);
if (!$result->isSuccess()) {
    // обработка ошибки
}
Примечание: Для изменения пользовательского свойства типа Y/N мы должны отдавать Y/0, а не Y/N как обычно