Использование Expression для фильтров
Во многих операциях получения данных с сервера на клиента, таких как МенеджерДанных.ВернутьСписокСущностей, МенеджерДанных.ВернутьЗначение, МенеджерДанных.ВернутьКоллекциюЗначений, формах выбора Диалоги.ВыборИзСпискаСущностей, а также в различных фильтрах и умолчаниях представлений и выражений фильтров связанных сущностей, для удобства написания используются так называемые выражения: 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()); .... } }