LINQ-to-SQL против хранимых процедур?
Я посмотрел пост "Руководство для начинающих по LINQ" здесь, в Stackru ( Руководство для начинающих по LINQ), но у меня возник дополнительный вопрос:
Мы собираемся запустить новый проект, где почти все наши операции с базами данных будут довольно простыми поисками данных (есть еще один сегмент проекта, который уже записывает данные). Большинство других наших проектов до этого момента используют хранимые процедуры для таких вещей. Тем не менее, я хотел бы использовать LINQ-to-SQL, если это имеет больше смысла.
Итак, вопрос таков: для простого поиска данных, какой подход лучше, LINQ-to-SQL или хранимые процедуры? Какие-то конкретные плюсы или минусы?
Благодарю.
23 ответа
Некоторые преимущества LINQ перед sprocs:
- Тип безопасности: я думаю, мы все это понимаем.
- Абстракция: это особенно верно для LINQ-to-Entities. Эта абстракция также позволяет инфраструктуре добавлять дополнительные улучшения, которыми вы можете легко воспользоваться. PLINQ - это пример добавления поддержки многопоточности в LINQ. Изменения кода минимальны, чтобы добавить эту поддержку. Было бы НАМНОГО сложнее сделать этот код доступа к данным, который просто вызывает sprocs.
- Поддержка отладки: я могу использовать любой отладчик.NET для отладки запросов. С sprocs вы не можете легко отлаживать SQL, и этот опыт во многом связан с вашим поставщиком базы данных (MS SQL Server предоставляет анализатор запросов, но часто этого недостаточно).
- Независимость от поставщика: LINQ работает с большим количеством баз данных, и количество поддерживаемых баз данных будет только увеличиваться. Sprocs не всегда переносимы между базами данных либо из-за изменяющегося синтаксиса, либо из-за поддержки функций (если база данных вообще поддерживает sprocs).
- Развертывание: другие уже упоминали об этом, но проще развернуть одну сборку, чем развернуть набор sprocs. Это также связано с № 4.
- Проще: вам не нужно изучать T-SQL для доступа к данным, а также не нужно изучать API доступа к данным (например, ADO.NET), необходимый для вызова sprocs. Это связано с № 3 и № 4.
Некоторые недостатки LINQ против sprocs:
- Сетевой трафик: sprocs должен только сериализовать sproc-имя и данные аргумента по сети, в то время как LINQ отправляет весь запрос. Это может быть очень плохо, если запросы очень сложны. Тем не менее, абстракция LINQ позволяет Microsoft улучшать это с течением времени.
- Менее гибкий: Sprocs может в полной мере использовать набор функций базы данных. LINQ имеет тенденцию быть более универсальным в своей поддержке. Это распространено в любой языковой абстракции (например, C# против ассемблера).
- Перекомпиляция: если вам нужно внести изменения в способ доступа к данным, вам необходимо перекомпилировать, установить версию и заново развернуть сборку. Sprocs иногда позволяет администратору БД настраивать процедуру доступа к данным без необходимости что-либо повторно развертывать.
Безопасность и управляемость - это то, о чем спорят и люди.
- Безопасность. Например, вы можете защитить свои конфиденциальные данные, ограничив прямой доступ к таблицам, и добавить списки ACL в sprocs. Однако с помощью LINQ вы все еще можете ограничить прямой доступ к таблицам и вместо этого поместить ACL в обновляемые представления таблиц для достижения аналогичного результата (при условии, что ваша база данных поддерживает обновляемые представления).
- Управляемость. Использование представлений также дает вам преимущество в защите вашего приложения от изменений схемы (таких как нормализация таблиц). Вы можете обновить представление, не требуя изменения кода доступа к данным.
Раньше я был большим напарником, но я начинаю склоняться к LINQ как к лучшей альтернативе в целом. Если в некоторых областях sprocs явно лучше, то я, вероятно, все еще напишу sproc, но получу к нему доступ через LINQ.:)
Как правило, я сторонник того, чтобы помещать все в хранимые процедуры, по всем причинам, по которым администраторы базировались годами. В случае Linq верно то, что не будет разницы в производительности с простыми запросами CRUD.
Но имейте в виду несколько вещей при принятии этого решения: использование любого ORM тесно связывает вас с вашей моделью данных. Администратор баз данных не имеет свободы вносить изменения в модель данных, не заставляя вас изменять скомпилированный код. С помощью хранимых процедур вы можете скрыть такого рода изменения в некоторой степени, поскольку список параметров и набор (ы) результатов, возвращаемые из процедуры, представляют ее контракт, а внутренние параметры можно изменять, лишь бы этот контракт все еще выполнялся.,
А также, если Linq используется для более сложных запросов, настройка базы данных становится гораздо более сложной задачей. Когда хранимая процедура выполняется медленно, администратор базы данных может полностью сосредоточиться на изолированном коде и имеет множество опций, чтобы контракт по-прежнему выполнялся, когда он / она выполнял.
Я видел много-много случаев, когда серьезные проблемы в приложении решались путем изменения схемы и кода в хранимых процедурах без каких-либо изменений в развернутом скомпилированном коде.
Возможно, гибридный подход был бы хорош с Linq? Конечно, Linq можно использовать для вызова хранимых процедур.
Linq to Sql.
Сервер Sql будет кешировать планы запросов, поэтому для sprocs нет прироста производительности.
С другой стороны, ваши операторы linq будут логически частью и проверены вашим приложением. Sprocs всегда немного отделены друг от друга и их сложнее поддерживать и тестировать.
Если бы я сейчас работал над новым приложением с нуля, я бы просто использовал Linq, а не sprocs.
Для получения основных данных я бы пошел на Linq без колебаний.
После переезда в Линк я обнаружил следующие преимущества:
- Отладка моего DAL никогда не была проще.
- Скомпилируйте безопасность времени, когда ваша схема изменится, и это бесценно.
- Развертывание проще, потому что все скомпилировано в DLL. Больше не нужно управлять сценариями развертывания.
- Поскольку Linq может поддерживать запросы ко всему, что реализует интерфейс IQueryable, вы сможете использовать тот же синтаксис для запроса XML, объектов и любых других источников данных без необходимости изучения нового синтаксиса.
LINQ будет раздувать кеш процедур
Если приложение использует LINQ to SQL и в запросах используются строки, длина которых может сильно варьироваться, кэш процедур SQL Server будет раздутым с одной версией запроса для каждой возможной длины строки. Например, рассмотрим следующие очень простые запросы, созданные для таблицы Person.AddressTypes в базе данных AdventureWorks2008:
var p =
from n in x.AddressTypes
where n.Name == "Billing"
select n;
var p =
from n in x.AddressTypes
where n.Name == "Main Office"
select n;
Если оба этих запроса будут выполнены, мы увидим две записи в кэше процедур SQL Server: одна связана с NVARCHAR(7), а другая - с NVARCHAR(11). Теперь представьте, были ли сотни или тысячи различных входных строк, все с различной длиной. Кэш процедур станет излишне заполненным различными планами для одного и того же запроса.
Подробнее здесь: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=363290&wa=wsignin1.0
Я думаю, что аргумент pro LINQ, похоже, исходит от людей, у которых нет истории разработки баз данных (в целом).
Особенно если использовать такой продукт, как VS DB Pro или Team Suite, многие из приведенных здесь аргументов неприменимы, например:
Сложнее в обслуживании и тестировании: VS предоставляет полную проверку синтаксиса, проверку стиля, проверку ссылок и ограничений и многое другое. Он также предоставляет все возможности модульного тестирования и инструменты рефакторинга.
LINQ делает истинное модульное тестирование невозможным, поскольку (на мой взгляд) он не проходит тест ACID.
Отладка проще в LINQ: почему? VS позволяет полный переход от управляемого кода и регулярную отладку SP.
Скомпилирован в одну DLL, а не в сценарии развертывания. И снова VS приходит на помощь, где она может создавать и развертывать полные базы данных или вносить изменения, безопасные для данных.
Не нужно изучать TSQL с помощью LINQ. Нет, не нужно, но вы должны изучать LINQ - в чем выгода?
Я действительно не вижу в этом пользы. Возможность что-то изменить в изоляции может показаться хорошим в теории, но только то, что изменения соответствуют контракту, не означает, что он возвращает правильные результаты. Чтобы иметь возможность определить, каковы правильные результаты, вам нужен контекст, и вы получите этот контекст из вызывающего кода.
Хм, слабосвязанные приложения являются конечной целью всех хороших программистов, поскольку они действительно увеличивают гибкость. Возможность изменять что-то изолированно - это просто фантастика, и именно ваши юнит-тесты по-прежнему будут показывать соответствующие результаты.
Прежде чем вы все расстроитесь, я думаю, что у LINQ есть свое место и большое будущее. Но для сложных приложений, интенсивно использующих данные, я не думаю, что они готовы заменить хранимые процедуры. Эту точку зрения я поддержал в MVP TechEd в этом году (они останутся безымянными).
РЕДАКТИРОВАТЬ: сторона вещей, хранимых процедур LINQ to SQL - это то, о чем мне еще нужно почитать - в зависимости от того, что я найду, я могу изменить свой вышеупомянутый текст;
LINQ является новым и имеет свое место. LINQ не изобретен, чтобы заменить хранимую процедуру.
Здесь я остановлюсь на некоторых мифах о производительности и CONS, только для "LINQ to SQL", конечно, я могу быть совершенно неправ;-)
(1) Люди говорят, что LINQ-статистика может "кэшироваться" на SQL-сервере, поэтому она не теряет производительность. Частично верно. "LINQ to SQL" фактически является средой выполнения, переводящей синтаксис LINQ в статистику TSQL. Таким образом, с точки зрения производительности, жестко запрограммированный оператор ADO.NET SQL не имеет различий, чем LINQ.
(2) В качестве примера пользовательский интерфейс службы поддержки клиентов имеет функцию "переноса счета". сама эта функция может обновлять 10 таблиц БД и возвращать некоторые сообщения за один раз. С помощью LINQ вы должны создать набор операторов и отправить их как один пакет на сервер SQL. производительность этого переведенного пакета LINQ->TSQL едва ли может соответствовать хранимой процедуре. Причина? поскольку вы можете настроить наименьшую единицу оператора в хранимой процедуре с помощью встроенного средства профилирования SQL и инструмента плана выполнения, вы не сможете сделать это в LINQ.
Дело в том, что когда речь идет об одной таблице БД и небольшом наборе данных CRUD, LINQ работает так же быстро, как и SP. Но для гораздо более сложной логики хранимая процедура более подстраивается под производительность.
(3) "LINQ to SQL" легко заставляет новичков вводить скачки производительности. Любой старший сотрудник TSQL может сказать вам, когда не следует использовать CURSOR (в большинстве случаев вам не следует использовать CURSOR в TSQL). С LINQ и очаровательным циклом "foreach" с запросом новичку так легко написать такой код:
foreach(Customer c in query)
{
c.Country = "Wonder Land";
}
ctx.SubmitChanges();
Вы можете видеть, что этот простой приличный код настолько привлекателен. Но под капотом.NET runtime просто переводит это в пакет обновления. Если есть только 500 строк, это 500 строк TSQL-пакета; Если есть миллионы строк, это хит. Конечно, опытный пользователь не будет использовать этот способ для выполнения этой работы, но дело в том, что так легко упасть таким образом.
Лучший код - это не код, и с помощью хранимых процедур вы должны написать хотя бы некоторый код в базе данных и код в приложении для его вызова, тогда как для LINQ to SQL или LINQ to Entities вам не нужно писать никаких дополнительных код за пределами любого другого запроса LINQ, кроме создания объекта контекста.
LINQ определенно имеет свое место в специфичных для приложений базах данных и в малых предприятиях.
Но в крупном предприятии, где центральные базы данных служат центром общих данных для многих приложений, нам нужна абстракция. Нам необходимо централизованно управлять безопасностью и показывать историю доступа. Нам необходимо уметь анализировать влияние: если я внесу небольшое изменение в модель данных для удовлетворения новых потребностей бизнеса, какие запросы необходимо изменить и какие приложения необходимо повторно протестировать? Представления и хранимые процедуры дают мне это. Если LINQ сможет сделать все это и сделать наших программистов более продуктивными, я приветствую это - есть ли у кого-нибудь опыт использования этого в такой среде?
Администратор баз данных не имеет свободы вносить изменения в модель данных, не заставляя вас изменять скомпилированный код. С помощью хранимых процедур вы можете скрыть такого рода изменения в некоторой степени, поскольку список параметров и набор (ы) результатов, возвращаемые из процедуры, представляют ее контракт, а внутренние параметры можно изменять, лишь бы этот контракт все еще выполнялся.,
Я действительно не вижу в этом пользы. Возможность что-то изменить в изоляции может показаться хорошим в теории, но только то, что изменения соответствуют контракту, не означает, что он возвращает правильные результаты. Чтобы иметь возможность определить, каковы правильные результаты, вам нужен контекст, и вы получите этот контекст из вызывающего кода.
ИМХО, RAD = LINQ, RUP = сохраненные процессы. Я много лет работал в крупной компании из списка Fortune 500, на многих уровнях, включая менеджмент, и, честно говоря, я бы никогда не нанял разработчиков RUP для разработки RAD. Они настолько обособлены, что очень ограничены в знаниях о том, что делать на других уровнях процесса. В изолированной среде имеет смысл предоставить администраторам БД контроль над данными через очень специфические точки входа, потому что другие, откровенно говоря, не знают наилучших способов управления данными.
Но крупные предприятия движутся мучительно медленно на арене развития, и это чрезвычайно дорого. Есть моменты, когда вам нужно двигаться быстрее, чтобы сэкономить время и деньги, и LINQ предоставляет это и многое другое.
Иногда я думаю, что администраторы баз данных предвзяты по отношению к LINQ, потому что считают, что это угрожает безопасности их работы. Но это природа зверя, дамы и господа.
Я думаю, что вам нужно идти с процессами для чего-то реального.
A) Запись всей вашей логики в linq означает, что ваша база данных менее полезна, потому что ее может использовать только ваше приложение.
Б) Я не уверен, что объектное моделирование лучше, чем реляционное моделирование.
C) Тестирование и разработка хранимой процедуры в SQL - это намного быстрее, чем цикл редактирования компиляции в любой среде Visual Studio. Вы просто редактируете, F5 и нажимаете кнопку выбора, и вы отправляетесь в гонки.
D) Управлять и развертывать хранимые процедуры проще, чем сборки. Вы просто помещаете файл на сервер и нажимаете F5...
E) Linq to sql по-прежнему пишет дрянной код иногда, когда вы этого не ожидаете.
Честно говоря, я думаю, что в конечном итоге MS мог бы увеличить t-sql, чтобы он мог имплицитно проецировать соединение, как это делает linq. t-sql должен знать, если вы хотите сделать, например, order.lineitems.part.
LINQ не запрещает использование хранимых процедур. Я использовал смешанный режим с LINQ-SQL и LINQ-storeproc. Лично я рад, что мне не нужно писать сохраненные процы....pwet-tu.
По словам гуру, я определяю LINQ как мотоцикл, а SP как автомобиль. Если вы хотите отправиться в короткую поездку и у вас есть только маленькие пассажиры (в данном случае 2), сделайте это изящно с LINQ. Но если вы хотите отправиться в путешествие и иметь большую группу, я думаю, вам следует выбрать SP.
В заключение, выбор между мотоциклом или автомобилем зависит от вашего маршрута (бизнес), длины (время) и пассажиров (данные).
Надеюсь, это поможет, я могу ошибаться.:D
Также существует проблема возможного отката 2.0. Поверьте мне, это случилось со мной пару раз, поэтому я уверен, что это случилось с другими.
Я также согласен, что абстракция лучше. Наряду с тем, что первоначальная цель любого ORM состоит в том, чтобы СУБД соответствовала концепциям ОО. Однако, если до LINQ все работало нормально, нужно немного отклониться от концепций ОО, то пошлите им. Концепции и реальность не всегда хорошо сочетаются друг с другом. В IT нет места воинствующим фанатикам.
Я предполагаю, что вы имеете в виду Linq To Sql
Для любой команды CRUD легко профилировать производительность хранимой процедуры по сравнению с любой технологией. В этом случае любая разница между ними будет незначительной. Попробуйте профилировать для объекта поля 5 (простых типов) более 100000 запросов на выборку, чтобы выяснить, есть ли реальная разница.
С другой стороны, реальным нарушителем будет вопрос о том, удобно ли вам размещать свою бизнес-логику в базе данных или нет, что является аргументом против хранимых процедур.
Все эти ответы, склоняющиеся к LINQ, в основном говорят о ПРОСТОТЕ РАЗВИТИЯ, которое более или менее связано с низким качеством кодирования или ленивостью в кодировании. Я только такой.
Некоторые преимущества или Linq, я читал здесь как: простота тестирования, простота отладки и т. Д., Но они не связаны с конечным выходом или конечным пользователем. Это всегда вызывает проблемы у конечного пользователя по производительности. Какой смысл загружать много вещей в память, а затем применять фильтры при использовании LINQ?
Опять же, TypeSafety - это предостережение о том, что "мы стараемся избегать неправильной типизации", что опять-таки плохое качество, которое мы пытаемся улучшить с помощью linq. Даже в этом случае, если что-то в базе данных изменится, например, размер столбца String, то linq необходимо перекомпилировать и без этого не быть безопасным для типов.. Я пытался.
Несмотря на то, что мы обнаружили, что это хорошо, приятно, интересно и т. Д. При работе с LINQ, у него есть существенный недостаток, заключающийся в том, что он делает разработчика ленивым:), и 1000 раз доказано, что это плохо (может быть и хуже) по производительности по сравнению с Stored Procs.
Хватит лениться. Я стараюсь изо всех сил.:)
Хранимая процедура облегчает тестирование, и вы можете изменить запрос, не касаясь кода приложения. Также с linq получение данных не означает правильные данные. А проверка правильности данных означает запуск приложения, но с помощью хранимой процедуры это легко проверить, не касаясь приложения.
Для простых операций CRUD с одной точкой доступа к данным, я бы сказал, пойти на LINQ, если вы чувствуете себя комфортно с синтаксисом. Для более сложной логики я думаю, что sprocs более эффективны с точки зрения производительности, если вы хорошо разбираетесь в T-SQL и его более сложных операциях. У вас также есть помощь от Tuning Advisor, SQL Server Profiler, отладки ваших запросов из SSMS и т. Д.
Результат может быть обобщен как
LinqToSql для небольших сайтов и прототипов. Это действительно экономит время для прототипирования.
СПС: Универсальный. Я могу точно настроить свои запросы и всегда проверять ActualExecutionPlan / EstimatedExecutionPlan.
Create PROCEDURE userInfoProcedure
-- Add the parameters for the stored procedure here
@FirstName varchar,
@LastName varchar
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
SELECT FirstName , LastName,Age from UserInfo where FirstName=@FirstName
and LastName=@FirstName
END
GO
http://www.totaldotnet.com/Article/ShowArticle121_StoreProcBasic.aspx
И LINQ, и SQL имеют свои места. Оба имеют свои недостатки и преимущества.
Иногда для сложного поиска данных вам могут понадобиться хранимые процедуры. Иногда вы можете захотеть, чтобы другие люди использовали ваш сохраненный процесс в Sql Server Management Studio.
Linq to Entities отлично подходит для быстрой разработки CRUD.
Конечно, вы можете создать приложение, используя только одно или другое. Или вы можете смешать это. Все сводится к вашим требованиям. Но хранимые в SQL процедуры не исчезнут в ближайшее время.