Как использовать Entity + LINQ не просто по существу жесткое кодирование моих запросов?

Итак, я немного развился с Entity + LINQ, и я действительно начинаю задумываться о лучших практиках. Я привык к модели "если мне нужно получить данные, обратитесь к хранимой процедуре". Сохраненные процедуры могут быть изменены "на лету" при необходимости и не требуют перекомпиляции кода. Я обнаружил, что мои запросы в моем коде выглядят следующим образом:

List<int> intList = (from query in context.DBTable
                     where query.ForeignKeyId == fkIdToSearchFor
                     select query.ID).ToList();

и я начинаю задаваться вопросом, какая разница между этим и этим:

List<int> intList = SomeMgrThatDoesSQLExecute.GetResults(
                                  string.Format("SELECT [ID]
                                                 FROM DBTable
                                                 WHERE ForeignKeyId = {0}",
                                  fkIdToSearchFor));

Меня беспокоит то, что я по сути жестко кодирую запрос в код. Я что-то упускаю? Это точка сущности? Если мне нужно выполнить какую-либо реальную работу запроса, я должен положить ее в sproc?

Ответ 1

Я лично избегаю жестких запросов SQL (как ваш второй пример). Написание LINQ вместо реального SQL позволяет:

  • простота использования (Intellisense, проверка типа...)
  • власть языка LINQ (который в большинстве случаев более прост, чем SQL, когда есть некоторая сложность, несколько соединений... и т.д.).
  • власть анонимные типы
  • видеть ошибки прямо сейчас во время компиляции, а не во время выполнения через два месяца...
  • лучше рефакторинг, если вы хотите переименовать таблицу/столбец/... (вы не забудете переименовать что-нибудь с LINQ из-за проверки времени компиляции)
  • Свободная связь между вашими запросами и вашей базой данных (что, если вы перейдете от Oracle к SQL Server? С LINQ вы не измените свой код, с жестко запрограммированными запросами вам придется просмотреть все ваши запросы)
  • LINQ и хранимые процедуры: вы помещаете логику в свой код, а не в свою базу данных. См. Обсуждение здесь.

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

- > если вам нужно обновить свою модель, вам, вероятно, также придется обновить свой код, чтобы принять во внимание обновление БД. Поэтому я не думаю, что это поможет вам избежать перекомпиляции большую часть времени.

Ответ 2

Сила Linq не делает себя очевидной, пока вам не нужны более сложные запросы.

В вашем примере подумайте о том, что вам нужно будет сделать, если вы хотите применить к вашему запросу фильтр какой-либо формы. Используя построенный строкой SQL, вам придется добавлять значения в построитель строк, защищенные от SQL-инъекций (или пройти дополнительное усилие подготовки оператора с параметрами).

Предположим, вы хотели добавить оператор в свой запрос linq;

IQueryable<Table> results = from query in context.Table
                            where query.ForeignKeyId = fldToSearchFor
                            select query;

Это можно сделать и сделать,

results.Where( r => r.Value > 5);

Результат sql будет выглядеть следующим образом:

SELECT * FROM Table WHERE ForeignKeyId = fldToSearchFor AND Value > 5

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

Ответ 3

Да, если вы хорошо разбираетесь в SQL, вы можете получить все с сохраненными процессами и получить более высокую производительность и некоторые преимущества обслуживания.

С другой стороны, LINQ безопасен по типу, немного проще в использовании (как разработчики привыкли к нему из сценариев не-db) и может использоваться с разными провайдерами (он может переходить на код, специфичный для провайдера). Все, что реализует IQueriable, можно использовать аналогично с LINQ.

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

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

Ответ 4

Является ли LINQ жестко кодировать все ваши запросы в ваше приложение? Да, абсолютно.

Давайте рассмотрим, что это означает для вашего приложения.

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

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

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

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

В этом очень конкретном сценарии, когда вы либо не делаете изменения в запросе, либо ваше приложение игнорирует изменения, вы получаете возможность развертывать свое SQL-изменение без необходимости касаться приложения или сбрасывать его за любое количество времени (или если вы работаете на настольных компьютерах, разверните новую версию).


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

Единственная причина реальной использовать Хранимые процедуры над LINQ - это если вы хотите поделиться своей базой данных между несколькими системами, используя согласованный API на уровне SQL. Это довольно ужасная ситуация, и я предпочел бы создать слой обслуживания поверх базы данных SQL, чтобы уйти от этого проекта.

Ответ 5

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

Java-магазины придерживаются этой парадигмы, потому что у них нет инструмента, такого как linq, и придерживаться этой парадигмы из-за необходимости. Базы данных с .Net обнаруживают, что необходимость в персоне базы данных убирается, если не полностью удалена, потому что, когда структура на месте, данные могут быть управляемы более эффективно (как показывают все остальные респонденты этого сообщения ) в слое данных, используя linq, чем исходный SQL.

Если у вас есть шанс использовать code first и создать модель базы данных с нуля, сначала создав классы сущности в коде и затем запустить EF, чтобы сделать магию создания базы данных... каждый понимает, как база данных действительно является инструментом, который хранит данные и необходимость хранимых процедур, а выделенный dba не нужен.