LINQ-to-SQL против хранимых процедур?

Я просмотрел сообщение «Руководство для начинающих по LINQ» здесь, в StackOverflow ( Руководство для начинающих по LINQ ), но у меня возник следующий вопрос:

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

Итак, вопрос таков: какой подход лучше для простого извлечения данных, LINQ-to-SQL или хранимые процедуры? Есть какие-то конкретные плюсы или минусы?

Спасибо.

Ответов (22)

Решение

Некоторые преимущества LINQ перед sprocs:

  1. Типовая безопасность : я думаю, мы все это понимаем.
  2. Абстракция : это особенно верно для LINQ-to-Entities . Эта абстракция также позволяет фреймворку добавлять дополнительные улучшения, которыми вы можете легко воспользоваться. PLINQ - это пример добавления поддержки многопоточности в LINQ. Изменения кода минимальны, чтобы добавить эту поддержку. Было бы НАМНОГО сложнее сделать этот код доступа к данным, который просто вызывает sprocs.
  3. Поддержка отладки : я могу использовать любой отладчик .NET для отладки запросов. С помощью sprocs вы не можете легко отлаживать SQL, и этот опыт во многом зависит от поставщика вашей базы данных (MS SQL Server предоставляет анализатор запросов, но часто этого недостаточно).
  4. Независимость от производителя : LINQ работает с большим количеством баз данных, и количество поддерживаемых баз данных будет только увеличиваться. Sprocs не всегда переносимы между базами данных либо из-за различного синтаксиса, либо из-за поддержки функций (если база данных вообще поддерживает sprocs).
  5. Развертывание : другие уже упоминали об этом, но проще развернуть одну сборку, чем развернуть набор sprocs. Это также связано с №4.
  6. Проще : вам не нужно изучать T-SQL для доступа к данным, и вам не нужно изучать API доступа к данным (например, ADO.NET), необходимый для вызова sprocs. Это связано с № 3 и № 4.

Некоторые недостатки LINQ vs sprocs:

  1. Сетевой трафик : sproc нужно только сериализовать имя sproc и данные аргумента по сети, в то время как LINQ отправляет весь запрос. Это может стать очень плохим, если запросы очень сложные. Однако абстракция LINQ позволяет Microsoft со временем улучшить это.
  2. Менее гибкий : Sprocs может в полной мере использовать набор функций базы данных. LINQ имеет тенденцию быть более универсальной в своей поддержке. Это обычное дело в абстракциях любого языка (например, C# или ассемблер).
  3. Перекомпиляция : если вам нужно внести изменения в способ доступа к данным, вам необходимо перекомпилировать, версию и повторно развернуть сборку. Sprocs может иногда позволить администратору базы данных настроить процедуру доступа к данным без необходимости перераспределять ничего.

О безопасности и управляемости тоже спорят.

  1. Безопасность : например, вы можете защитить свои конфиденциальные данные, напрямую ограничив доступ к таблицам и поместив ACL в sprocs. С помощью LINQ, однако, вы можете ограничить прямой доступ к таблицам и вместо того, чтобы положить списки ACL на обновляемых таблицах взглядов для достижения аналогичного конца (предполагается , что ваша база данных поддерживают обновляемые представления).
  2. Управляемость : использование представлений также дает вам преимущество защиты вашего приложения от изменений схемы (например, нормализации таблиц). Вы можете обновить представление, не требуя изменения кода доступа к данным.

Раньше я был большим парнем в области sproc, но я начинаю склоняться к LINQ как к лучшей альтернативе в целом. Если есть области, где sproc явно лучше, я, вероятно, все равно напишу sproc, но получу к нему доступ с помощью LINQ. :)

Linq в Sql.

Sql-сервер будет кэшировать планы запросов, поэтому для sprocs не будет прироста производительности.

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

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

Администратор баз данных не имеет права вносить изменения в модель данных, не заставляя вас изменять скомпилированный код. С помощью хранимых процедур вы можете до некоторой степени скрыть такого рода изменения, поскольку список параметров и наборы результатов, возвращаемые процедурой, представляют ее контракт, а внутренности могут быть изменены до тех пор, пока этот контракт все еще выполняется. .

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

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 [email protected]
    and [email protected]
END
GO

http://www.totaldotnet.com/Article/ShowArticle121_StoreProcBasic.aspx

Я думаю нужно идти с проков ни на что реальное.

A) Написание всей вашей логики в linq означает, что ваша база данных менее полезна, потому что только ваше приложение может ее использовать.

Б) Я не уверен, что объектное моделирование лучше, чем реляционное моделирование.

C) Тестирование и разработка хранимой процедуры в SQL происходит намного быстрее, чем цикл редактирования компиляции в любой среде Visual Studio. Вы просто редактируете, F5 и нажимаете select, и вы отправляетесь в гонку.

D) Хранимые процедуры проще управлять и развертывать, чем сборки .. вы просто кладете файл на сервер и нажимаете F5 ...

E) Linq to sql по-прежнему пишет дрянной код, когда вы этого не ожидаете.

Честно говоря, я думаю, что в конечном итоге MS могла бы дополнить t-sql, чтобы он мог выполнять проекцию соединения неявно, как это делает linq. t-sql должен знать, хотите ли вы, например, сделать order.lineitems.part.

Хранимая процедура упрощает тестирование, и вы можете изменить запрос, не касаясь кода приложения. Также с linq получение данных не означает, что это правильные данные. А проверка правильности данных означает запуск приложения, но с хранимой процедурой его легко проверить, не касаясь приложения.

Для простых операций CRUD с единственной точкой доступа к данным я бы посоветовал перейти на LINQ, если вы чувствуете себя комфортно с синтаксисом. Я думаю, что для более сложной логики sprocs более эффективны с точки зрения производительности, если вы хорошо разбираетесь в T-SQL и его более сложных операциях. У вас также есть помощь от Tuning Advisor, SQL Server Profiler, отладки ваших запросов из SSMS и т. Д.

Все эти ответы, склоняющиеся к LINQ, в основном говорят о ПРОСТОТА РАЗРАБОТКИ, которая более или менее связана с низким качеством кодирования или ленью в кодировании. Я только такой.

Я читаю здесь некоторые преимущества Linq: их легко протестировать, легко отладить и т. Д., Но они не связаны с Final output или конечным пользователем. Это всегда вызывает проблемы с производительностью конечного пользователя. Какой смысл загружать много вещей в память, а затем применять фильтры при использовании LINQ?

Опять же TypeSafety - это предупреждение о том, что «мы осторожны, чтобы избежать неправильного приведения типов», что опять же плохого качества, которое мы пытаемся улучшить с помощью linq. Даже в этом случае, если что-то в базе данных изменится, например, размер столбца String, тогда linq необходимо перекомпилировать, и без этого он не будет безопасным по типу .. Я пробовал.

Хотя мы обнаружили, что при работе с LINQ это хорошо, мило, интересно и т. Д., У него есть серьезный недостаток, заключающийся в том, что разработчик становится ленивым :) и 1000 раз доказано, что это плохо (может быть хуже) с точки зрения производительности по сравнению с хранимыми процедурами.

Перестань лениться. Я очень стараюсь. :)

Я вообще сторонник размещения всего в хранимых процедурах по всем причинам, о которых администраторы баз данных твердят в течение многих лет. В случае с Linq, правда, не будет разницы в производительности с простыми запросами CRUD.

Но помните о нескольких вещах, принимая это решение: использование любого ORM тесно связывает вас с вашей моделью данных. Администратор баз данных не имеет права вносить изменения в модель данных, не заставляя вас изменять скомпилированный код. С помощью хранимых процедур вы можете до некоторой степени скрыть такого рода изменения, поскольку список параметров и наборы результатов, возвращаемые процедурой, представляют ее контракт, а внутренности могут быть изменены до тех пор, пока этот контракт все еще выполняется. .

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

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

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

Лучший код - это отсутствие кода, и с хранимыми процедурами вам нужно написать хотя бы некоторый код в базе данных и код в приложении для его вызова, тогда как с LINQ to SQL или LINQ to Entities вам не нужно писать никаких дополнительных код, превосходящий любой другой запрос LINQ, кроме создания экземпляра объекта контекста.

Я предполагаю, что вы имеете в виду Linq To Sql

Для любой команды CRUD легко профилировать производительность хранимой процедуры по сравнению с любой технологией. В этом случае разница между ними будет незначительной. Попробуйте профилировать для объекта поля 5 (простых типов) более 100 000 запросов на выборку, чтобы выяснить, есть ли реальная разница.

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

Для получения базовых данных я бы без колебаний выбрал Linq.

С момента перехода на Linq я обнаружил следующие преимущества:

  1. Отладка моего DAL еще никогда не была такой простой.
  2. Безопасность времени компиляции при изменении схемы бесценна.
  3. Развертывание проще, потому что все скомпилировано в библиотеки DLL. Больше не нужно управлять сценариями развертывания.
  4. Поскольку Linq может поддерживать запросы ко всему, что реализует интерфейс IQueryable, вы сможете использовать тот же синтаксис для запроса XML, объектов и любого другого источника данных без необходимости изучать новый синтаксис.

LINQ не запрещает использование хранимых процедур. Я использовал смешанный режим с LINQ-SQL и LINQ-storedproc . Лично я рад, что мне не нужно писать сохраненные процедуры .... pwet-tu.

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

Я думаю, что аргумент в пользу 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 может сделать все это и сделать наших программистов более продуктивными, я буду приветствовать это - есть ли у кого-нибудь опыт его использования в такой среде?

Также существует проблема возможного отката 2.0. Поверьте, это случалось со мной пару раз, поэтому я уверен, что это случилось с другими.

Я также согласен с тем, что абстракция лучше всего. Наряду с этим, первоначальная цель ORM состоит в том, чтобы обеспечить соответствие РСУБД концепциям объектно-ориентированного программирования. Однако, если до LINQ все работало нормально из-за того, что приходилось немного отклоняться от концепций объектно-ориентированного проектирования, тогда к черту. Концепции и реальность не всегда хорошо сочетаются друг с другом. В IT нет места воинствующим фанатикам.

LINQ является новым и имеет свое место. LINQ изобретен не для замены хранимой процедуры.

Здесь я сосредоточусь на некоторых мифах о производительности и недостатках, только для «LINQ to SQL», конечно, я могу ошибаться ;-)

(1) Люди говорят, что статус LINQ может «кэшироваться» на сервере SQL, поэтому он не теряет производительности. Частично верно. «LINQ to SQL» фактически является средой выполнения, переводящей синтаксис LINQ в состояние TSQL. Таким образом, с точки зрения производительности жестко запрограммированный оператор SQL ADO.NET ничем не отличается от 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 просто переводит это в пакет обновлений. Если есть только 500 строк, это пакет TSQL на 500 строк; Если есть миллион строк, это хит. Конечно, опытный пользователь не воспользуется этим способом для выполнения этой работы, но дело в том, что так легко упасть.

ИМХО, RAD = LINQ, RUP = Stored Procs. Я много лет работал в крупной компании из списка Fortune 500, на многих уровнях, включая руководство, и, честно говоря, я бы никогда не нанял разработчиков RUP для разработки RAD. Они настолько разобщены, что у них очень ограниченные знания о том, что делать на других уровнях процесса. В изолированной среде имеет смысл предоставить администраторам баз данных контроль над данными через очень конкретные точки входа, потому что другие, откровенно говоря, не знают наилучших способов управления данными.

Но крупные предприятия болезненно медленно продвигаются на арене развития, а это чрезвычайно дорого. Бывают случаи, когда вам нужно действовать быстрее, чтобы сэкономить время и деньги, и LINQ предоставляет это и многое другое в избытке.

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

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

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

Надеюсь, это поможет, но я могу ошибаться. : D

И LINQ, и SQL имеют свои места. У обоих есть свои недостатки и преимущества.

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

Linq to Entities отлично подходит для быстрой разработки CRUD.

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

Результат можно резюмировать как

LinqToSql для небольших сайтов и прототипов. Это действительно экономит время на прототипирование.

СПС: универсальный. Я могу точно настроить свои запросы и всегда проверять ActualExecutionPlan / EstimatedExecutionPlan.