IEnumerable против IQueryable для бизнес-логики или типов возврата DAL

Я знаю, что эти вопросы задавались раньше, я начну с перечисления некоторых из них (тех, которые я читал до сих пор):

Как видите, есть отличные ресурсы только по SO по этой теме, но есть один вопрос / Я до сих пор не уверен, прочитал ли я все это полностью.

Меня в первую очередь беспокоит вопрос IEnumerable и IQueryable, и, в частности, связь между DAL и его ] потребителей .

Я нашел разные мнения относительно двух интерфейсов, и они оказались великолепными. Однако меня беспокоят последствия возврата IQueryable из DAL. Насколько я понимаю, IQueryable предполагает / подразумевает, что под капотом есть поставщик Linq. Это проблема номер один - что, если DAL внезапно потребует данные из источника, не предоставленного Linq? Следующее будет работать, но это скорее хакерская игра?

public static IQueryable GetAll()
{
    // this function used to use a L2S context or similar to return data 
    // from a database, however, now it uses a non linq provider

    // simulate the non linq provider...
    List results = new List { new Product() };
    return results.AsQueryable();
}

Итак, я могу использовать расширение AsQueryable (), хотя я не признаю, что точно знаю, что оно делает? Я всегда представляю IQueryables как базовые деревья выражений, которые мы можем добавлять по мере необходимости, пока мы не будем готовы выполнить наш запрос и получить результаты.

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

var results = SomeClass.GetAll().Where(x => x.ProductTypeId == 5);

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

Как другие люди обойти это?

  • Предоставить больше функций в DAL - GetAllByProductType, GetAllByStartDate, ... и т. д.
  • Предоставить перегрузку, которая принимает предикаты? то есть

     общедоступный статический IEnumerable  GetAll (предикат Predicate )
     {
    
      Список  результаты = новый Список  {новый продукт ()};
      вернуть результаты. Где (x => predicate (x));
     }
     

И последнее (извините, я знаю, очень длинный вопрос!).

Я обнаружил, что IEnumerable является наиболее рекомендуемым из всех проверенных мной вопросов, но как насчет требования отложенной загрузки для доступности контекста данных? ? Насколько я понимаю, если ваша функция возвращает IEnumerable, но вы возвращаете IQueryable, IQueryable зависит от базового контекста данных. Поскольку результат на этом этапе фактически является выражением и ничего не было занесено в память, вы не можете гарантировать, что потребитель DAL / функции будет выполнить запрос, ни когда. Итак, должен ли я каким-то образом сохранять доступным экземпляр контекста, из которого были получены результаты? Это как / почему используется шаблон «Единица работы»?

Сводка вопросов для ясности (выполнялся ли поиск «?» ...):

  1. Если вы используете IQueryable в качестве возвращаемого типа, вы тоже тесно связывает ваш пользовательский интерфейс / бизнес-логику с поставщиками Linq?
  2. Является ли использование расширения AsQueryable () хорошей идеей, если вам внезапно нужно вернуть данные из источника, не предоставленного Linq?
  3. У кого-нибудь есть хорошая ссылка, описывающая, как Пример преобразования стандартного списка в AsQueryable работает, что он на самом деле делает?
  4. Как вы обрабатываете дополнительные требования к фильтрации, предоставляемые бизнес-логикой для вашего DAL?
  5. Похоже, что отложенная загрузка IEnumerable и IQueryable зависит от поддержки базового провайдера, должен ли я использовать шаблон Unit of Work или что-то еще, чтобы справиться с этим?

Заранее большое спасибо!

24
задан Community 23 May 2017 в 12:26
поделиться