Как предложить использовать ORM вместо хранимых процедур?

31

Я работаю в компании, которая использует только хранимые процедуры для всего доступа к данным, что очень раздражает, когда мы синхронизируем наши локальные базы данных, так как каждый коммит мы должны запускать новые процессы. Я использовал некоторые базовые ORM в прошлом, и я считаю, что опыт намного лучше и чище. Я хотел бы предложить менеджеру по разработке и остальным членам команды, что мы рассмотрим использование ORM некоторого вида для будущей разработки (остальная часть команды знакома только с хранимыми процедурами и никогда не использовала ничего другого). Текущая архитектура - .NET 3.5, написанная как .NET 1.1, с «богами», которые используют странную реализацию ActiveRecord и возвращают нетипизированные наборы данных, которые зациклены в файлах с выделенным кодом - классы работают примерно так:

class Foo { 
    public bool LoadFoo() { 
        bool blnResult = false;
        if (this.FooID == 0) { 
            throw new Exception("FooID must be set before calling this method.");
        }

        DataSet ds = // ... call to Sproc
        if (ds.Tables[0].Rows.Count > 0) { 
            foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
            // other properties set
            blnResult = true;
        }
        return blnResult;
    }
}

// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...

Практически нет применения каких-либо шаблонов дизайна. Там нет никаких тестов вообще (никто больше не знает, как писать модульные тесты, и тестирование выполняется через загрузку веб-сайта вручную и поиск по нему). Просматривая нашу базу данных, мы имеем: 199 таблиц, 13 представлений, колоссальные 926 хранимых процедур и 93 функции. Около 30 или около того таблиц используются для пакетных заданий или внешних вещей, остальные используются в нашем основном приложении.

Стоит ли вообще придерживаться другого подхода в этом сценарии? Я говорю о продвижении вперед только потому, что нам не разрешается рефакторинг существующего кода, так как «он работает», поэтому мы не можем изменить существующие классы для использования ORM, но я не знаю, как часто мы добавляем новые модули вместо добавление / исправление текущих модулей, поэтому я не уверен, является ли ORM правильным подходом (слишком много вложено в хранимые процедуры и наборы данных). Если это правильный выбор, как мне представить кейс для его использования? Вдобавок ко всему, единственное преимущество, которое я могу придумать, это иметь более чистый код (хотя это может и не быть, поскольку текущая архитектура не ' t построены с учетом ORM, поэтому в основном мы будем включать ORMs присяжных в будущие модули, но старые по-прежнему будут использовать наборы данных) и меньше хлопот, чтобы помнить, какие скрипты процедур были запущены и какие должны быть запущены, и т.д., но это все, и я не знаю, насколько убедительным будет такой аргумент. Ремонтопригодность - это еще одна проблема, но кажется, что никто, кроме меня, не обеспокоен.

Уэйн Молина
источник
8
Похоже, у вас больше проблем, чем просто убедить команду использовать ORM. Мне кажется, что ваша команда не знает о некоторых хороших методах разработки (например, шаблоны проектирования, модульное тестирование). Это более важные вопросы, которые вам нужно решить.
Бернард
6
По иронии судьбы, я думаю, что примерно за 5 лет разработки я встретил лишь несколько человек / команд, которые знали о таких вещах, как шаблоны проектирования и модульное тестирование; обычно я единственный парень в компании, который знает об этих вещах.
Уэйн Молина
3
@Wayne M: Я нахожу это немного тревожным, но меня это тоже не удивляет.
Бернард
2
Я нахожу это очень ... удручающим. Странно, когда вы предлагаете что-то и получаете «олень в свете фар», который указывает на то, что другой человек не имеет ни малейшего представления о том, о чем вы говорите, или о том, почему кто-то когда-либо подумал бы сделать это. У меня такое случалось довольно много раз в прошлом.
Уэйн Молина
2
Я большой поклонник хранимой процедуры, поэтому мой комментарий предвзят, но я полностью не согласен со всей предпосылкой. Вам нравится ORM, и вы хотите использовать это нормально. Однако остальная часть команды в порядке с сохраненными процессами. Зачем заставлять их на то, что вам нравится?
Темная ночь

Ответы:

47

Хранимые процедуры плохие, они часто медленные и примерно такие же эффективные, как и обычный клиентский код.

[Ускорение обычно происходит из-за того, как спроектирован интерфейс клиента и хранимой процедуры, и из-за того, что транзакции записываются в виде коротких, сфокусированных пакетов SQL.]

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

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

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

Вам все равно придется время от времени обновлять схему и модель ORM. Однако изменения схемы изолированы от изменений ORM, что обеспечивает некоторую независимость между приложениями и схемой базы данных.

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

ORM не волшебство, и хорошие навыки проектирования баз данных абсолютно необходимы для его работы.

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

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

С. Лотт
источник
19
+1, потому что с хранимыми процедурами работать очень тяжело
Гэри Роу
3
: '(У меня нет проблем с хранимыми процедурами. Для меня это просто еще один уровень абстракции.
Майк Уэллер,
3
Если мы создадим SP, ядро ​​базы данных сохранит его в виде скомпилированной формы, и он создаст путь выполнения, чтобы он выполнялся как можно быстрее. Но ORM каждый раз отправляет SQL, который должен быть скомпилирован и запущен ядром базы данных. Я думаю, что будет медленнее использовать ORM вместо хранимой процедуры.
DeveloperArnab
4
Веселая. Мы переключились с ORM на хранимые процедуры только из-за ... СКОРОСТИ. Не количество времени, которое нам нужно для программирования, а время, необходимое ORM для таких вещей, как материализация объектов, поиск объекта, обновление на разных клиентах. ИП, где, черт возьми, намного быстрее. Один пример: чтение 30 000 объектов из БД с новыми современными потребностями ORM ... ну да ладно. Тайм-аут через 2 минуты. Вызов хранимой процедуры и получение результата - 2 секунды. Да, существует множество хитростей, таких как подкачка страниц, чтобы уменьшить количество позывных из БД, но большая разница, если они просто позволяют использовать ORM или
Offler
2
@DeveloperArnab: Это могло бы быть правдой 20 лет назад, но современные движки БД довольно сложны и могут распознавать ранее выполненные запросы и повторно использовать планы выполнения, в настоящее время разница в скорости настолько мала, что вряд ли оправдывает дополнительные хлопоты SP.
whatsisname
20

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

Интересно, администраторы баз данных сидят там и говорят: «О, каждый коммит, мне нужно снова и снова сбрасывать клиента, вместо этого мы должны переместить весь код в формы БД».

В вашем случае вы сможете заменить существующий пользовательский ORM (т.е. ваши забавные классы) на чужой без каких-либо потерь, за исключением изменений в способе написания кода с выделенным кодом. Вы также можете оставить SP, так как большинство (все?) ORM с радостью их вызовят. Поэтому я бы рекомендовал заменить эти классы "Foo" на ORM и перейти оттуда. Я бы не рекомендовал заменять ваши SP.

PS. Похоже, у вас много общего кода в классах code-behind, что делает их шаблоном дизайна сами по себе. Как вы думаете, шаблон дизайна на первом месте! (хорошо, это может быть не самым лучшим или даже хорошим, но это все еще DP)

Изменить: и теперь с Dapper , любая причина, чтобы избежать sprocs над тяжелой ORM исчезла.

gbjbaanb
источник
3
+1, очевидный первый шаг - перейти к ORM и использовать его для отображения результатов существующих хранимых процедур на объекты. Избавься от всего этого ds.Tables[0].Rows[0]["FooName"].ToString()дерьма. Менеджер любит хранимые процедуры? Он получает их. Но физически невозможно утверждать, что перемещение всего этого повторяющегося стандартного кода в нечто, сгенерированное, скажем, LINQ to SQL, было плохой вещью.
Carson63000
11
Ну, я не могу поверить, насколько "неправильно" есть в вашем посте. Ваше сравнение с администратором базы данных, жалующимся на необходимость вытащить код, неуместно и совершенно бессмысленно. Прежде всего, база данных - это СЕРВИС, предназначенная для хранения и извлечения данных, и конец истории. ЛОГИКА, как следует из названия, входит в уровень бизнес-логики, который является частью кода API. Приложение более хрупкое, удаляясь от звезд? Ты серьезно или просто троллинг? TDD приложение с логикой в ​​sprocs и скажите мне, как это весело. Также ORM не предназначены для переключения. Базы данных есть, так как они просто СЕРВИС.
Маттео Моска
5
Я не могу понять, почему некоторые люди думают, что база данных - это какая-то святая земля, где все священно. Думать об этом. Когда сторонняя компания предоставляет вам услугу, они дают вам прямой доступ к своей базе данных или маскируют ее за API? Чтобы использовать популярный пример, возьмите любой сервис Google. Вы, разработчик, подключаетесь к их общедоступному API, вы даже не знаете, какая база данных находится под ним, или вообще есть база данных. Вот как вы разрабатываете твердое и разобщенное программное обеспечение. Базы данных не предназначены для прямого доступа к приложениям. Для этого есть средние уровни.
Маттео Моска
5
@Matteo Mosca: конечно, но как промежуточное ПО обращается к БД ... это клиент для БД. «Клиент» не означает «GUI» или «приложение для ПК». Есть много серых областей на уровнях приложений - вы помещаете проверку в GUI или в логику сервера / бизнеса? На сервере должен быть чистый дизайн, но это будет очень плохо для производительности и отзывчивости пользователя. Точно так же вы часто помещаете некоторую логику в БД, когда это повышает производительность и (в данном случае) правильность данных.
gbjbaanb
4
Извините, но я все еще не согласен. В тот день, когда вам нужно будет развернуть свое приложение в другой среде, где у вас нет той же технологии БД, которую вы использовали, вы окажетесь в ситуации, когда ваше приложение не может работать, потому что у вас нет всех этих sprocs в новой базе данных ... и даже если вы воссоздаете их (что является полной проблемой), они могут отличаться из-за различий в диалектах SQL и т. д. Централизованный API с логикой и проверкой, предоставляемый через стандарт (например, SOAP или REST), решает эту проблему проблема, и добавляет тестируемость, управление версиями и согласованность.
Маттео Моска
13

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

Выложенный вами полусгоревший код реализации активной записи не особенно удобен - я бы порекомендовал исследовать шаблон репозитория, который легко понять и реализовать, и который очень популярен среди разработчиков .NET. Этот шаблон часто ассоциируется с ORM, но создавать репозитории с помощью простого ADO.NET также просто.

Что касается DataSet's - гадость! С вашими библиотеками классов будет намного легче работать, если вы возвращаете статически (или даже динамически) типизированные объекты. Я считаю, что эта иллюстрация объясняет мое мнение о DataSet лучше, чем я мог.

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

Я не препятствую использованию ORM - я обычно использую их в большинстве проектов, над которыми я работаю. Однако я понимаю, почему может быть много трений при попытке внедрить один в этот проект и вашу команду, которые, мягко говоря, звучат так, будто они перестали узнавать что-то новое около 8 лет назад. Сказав, что я определенно взгляну на новое поколение «микро-ORM», таких как Dapper (используется для питания этого сайта не меньше) и Massive , оба из которых невероятно просты в использовании и держат вас ближе к SQL, чем типичный ORM, и что ваша команда может быть более готова принять.

richeym
источник
2
Я думаю, что проблема заключается только в том, что когда приложение было написано, не было заметных реальных ORM для .NET, поэтому это было сделано другим способом (способом ASP.NET 1.1), и никто никогда не думал, что делать это (или что-то еще) иначе пока я не присоединился несколько месяцев назад.
Уэйн Молина
1
+1 для щеголя. Я только начал использовать его в проекте, и его очень легко реализовать и использовать. Я уже большой поклонник.
SLoret
4

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

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

Джастин
источник
3

JFTR - я скромный PHP-разработчик, но это звучит как политический вопрос.

Учитывая масштабы «гниения», поддерживающего приложение, тогда, если не учитывать лучшие практики , будут существенные накладные расходы на его устранение. Похоже, это граничит с территорией переписать.

Можете ли вы гарантировать, что предложенная вами альтернатива принесет пользу для оправдания затрат для бизнеса? Я подозреваю, что рентабельность инвестиций этого предприятия может быть трудно продать бизнесу. Если приложение не является нестабильным, или вы можете доказать ценность капитального ремонта в финансовом плане - это может оказаться затруднительным.

Является ли ORM единственной альтернативой SPROCS? Существует несколько шаблонов проектирования между полноценным ORM и ванильным SQL. Возможно, вы могли бы начать процесс, постепенно выводя эти SPROCS из DB в DBAL. Конечно, существует опасность, что со временем это превратится в доморощенный ОРМ, но вы бы приблизились к цели.

sunwukung
источник
2

Мы перешли с SP на ORM несколько лет назад.

В одном случае нам пришлось обновить 80 таблиц. Старая модель оценки оценивала бы это в 80 часов с помощью entlib и SP. Мы сделали это в 10 :)

Это позволило нам сократить время, затрачиваемое на разработку уровня доступа к данным, на 80%.

Шираз Бхайджи
источник
1
И вы не могли написать скрипт обновления таблицы, почему?
Темная ночь
Это заняло сложный объект в памяти и сохранило его в реляционной базе данных для отчетов. Мы написали программу, которая делала отражение в объекте для создания структуры таблицы.
Шираз Бхайджи
-1

Мне кажется, что основной причиной является то, что ваши развертывания не работают должным образом и автоматически.

Может быть проще настроить механизм непрерывной сборки, который знает, как манипулировать базами данных при необходимости после каждой фиксации.


источник