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

Материал из Fabius NET DEV
Перейти к: навигация, поиск

Во многих операциях получения данных с сервера на клиента, таких как МенеджерДанных.ВернутьСписокСущностей, МенеджерДанных.ВернутьЗначение, МенеджерДанных.ВернутьКоллекциюЗначений, формах выбора Диалоги.ВыборИзСпискаСущностей, а также в различных фильтрах и умолчаниях представлений и выражений фильтров связанных сущностей, для удобства написания используются так называемые выражения: System.Linq.Expressions.Expression

Типичный пример использования, для получения данных через МенеджерДанных:

namespace Fabius.Библиотека
{
    public class Реализация
    {
        ...
        public static void ПолучитьПлатежки()
        {

           ...
           var сохраненныеПлатежки = МенеджерДанных.ВернутьСписокСущностей<БанковскийДокумент>("ПринятьВыписку", DateTime.Today, false, false, true,
                    выражениеПоиска: (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim()));        
           ...
        }
        ....

    }
}

все что написано в параметре выражениеПоиска и является таким Expression и позволяет пользоватся подсказками типов Intellisence, а не выражениями фильтра типа string, что позовляет писать код быстрее и безошибочнее.

Другой вариант использования, с объявлением переменной типа Expression заранее:

namespace Fabius.Библиотека
{
    public class Реализация
    {
        ...
        public static void ПолучитьПлатежки()
        {
           ...
           Expression<Func<БанковскийДокумент, bool>> выражение = (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim());

           var сохраненныеПлатежки = МенеджерДанных.ВернутьСписокСущностей<БанковскийДокумент>("ПринятьВыписку", DateTime.Today, false, false, true, выражениеПоиска: выражение);        
           ...
        }
        ....

    }
}

Пример использования в фильтре связанной сущности:

namespace ШаблонДоставкиСобытия
{
    public partial class ШаблонДоставкиЭкспедицияФильтрСвязаннойСущности : IШаблонДоставкиЭкспедицияФильтрСвязаннойСущности
    {
        /// <summary>
        /// Если задан Филиал (параметр Роли), то Экспедиции только данного филиала
        /// </summary>
        public void Calculate(IШаблонДоставки сущность, IПредставление представление, ref string фильтр, ref System.Linq.Expressions.Expression выражениеФильтра)
        {
            if (сущность.ФилиалИД != null)
            {
                Guid ФилиалИД = (Guid)сущность.ФилиалИД;
                выражениеФильтра = (System.Linq.Expressions.Expression<Func<Экспедиция, bool>>)(p => p.ФилиалИД == ФилиалИД);
            }
        }
    }
}

Особенности использования:

Поскольку выражения типа System.Linq.Expression передаются на сервер - они являются сериализуемыми переменными, что накладывает на их использование определенные ограничения: Известны несколько особенностей использования Expression 1. Переменная для описания выражения вхождения Contains должна быть типа Array[], а не List<> Пример:

public static void ПолучитьПлатежки()
{
    //Неправильно
    var массивНомеровДляПоиска = НомераПлатежек.ToList<Guid>();
    ...
    Expression<Func<БанковскийДокумент, bool>> выражение = (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim());
    ....

    //Правильно
    var массивНомеровДляПоиска = НомераПлатежек.ToArray<Guid>();
    ...
    Expression<Func<БанковскийДокумент, bool>> выражение = (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim());
    ....

}

2. Переменная для описания выражения вхождения Contains должна быть описана выше чем блок if/else, где находится выражение, иначе Expression при сериализации его не увидит, Пример:

public static void ПолучитьПлатежки()
{
    //Неправильно
    if (НомераПлатежек.Any()) 
    {
        var массивНомеровДляПоиска = НомераПлатежек.ToList<Guid>();
 
        ...
        Expression<Func<БанковскийДокумент, bool>> выражение = (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim());
        ....
    }

    //Правильно    
    var массивНомеровДляПоиска = НомераПлатежек.ToList<Guid>();

    if (НомераПлатежек.Any()) 
    {         
        ...
        Expression<Func<БанковскийДокумент, bool>> выражение = (p) => масcивДатДляПоиска.Contains(p.ДатаДокумента) && массивНомеровДляПоиска.Contains(p.НомерДокумента.Trim());
        ....
    }
}

Смотрите также

Образцы кода и элементов Конфигурации