Пользовательские функции SQL против ветвления хранимых процедур - PullRequest
1 голос
/ 20 июля 2009

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

В настоящее время способ, которым разработано приложение, вызывает хранимую процедуру, а затем перезагружает интерфейс со свежим набором данных. Конечно, данные, которые мы хотим отобразить, все еще обрабатываются на стороне сервера SQL, поэтому результаты пользовательского интерфейса не отображаются полностью. Чтобы это исправить, я просто заставил поток спать в течение 30 секунд перед загрузкой пользовательского интерфейса. Это ужасный хак, и я бы хотел исправить это на стороне SQL.

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

Вот хранимая процедура:

    ALTER PROCEDURE [dbo].[ALLOCATE_BUDGET] 
    @budget_scenario_id uniqueidentifier
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @constraint_type varchar(25)

    -- get project cache id and constraint type
    SELECT @constraint_type = CONSTRAINT_TYPE
    FROM BUDGET_SCENARIO WHERE BUDGET_SCENARIO_ID = @budget_scenario_id

    -- constraint type is Region by Region
    IF (@constraint_type = 'Region by Region')
      EXEC BUDGET_ALLOCATE_SCENARIO_REGIONBYREGION @budget_scenario_id

    -- constraint type is City Wide
    IF (@constraint_type = 'City Wide')
      EXEC BUDGET_ALLOCATE_SCENARIO_CITYWIDE @budget_scenario_id

    -- constraint type is Do Nothing
    IF (@constraint_type = 'Do Nothing')
      EXEC BUDGET_ALLOCATE_SCENARIO_DONOTHING @budget_scenario_id

    -- constraint type is Unconstrained
    IF (@constraint_type = 'Unconstrained')
      EXEC BUDGET_ALLOCATE_SCENARIO_UNCONSTRAINED @budget_scenario_id

    --set budget scenario status to "Allocated", so reporting tabs in the application are populated
    EXEC BUDGET_UPDATE_SCENARIO_STATUS @budget_scenario_id, 'Allocated'
END

Чтобы избежать отображения неполного набора результатов в вызывающем пользовательском интерфейсе приложения .NET, до того, как курсоры в вызовах ветвления завершены, стоит ли преобразовывать эти хранимые процедуры в функции с возвращаемыми значениями? Вынудит ли это SQL ждать перед завершением основного вызова хранимой процедуры [ALLOCATED_BUDGET]?

  • Последний вызов оператора SQL в хранимой процедуре устанавливает состояние «Выделено». Это происходит до завершения обработки курсоров в предыдущих вызовах. Влияет ли выполнение этих вызовов на вызовы функций, как хранимая процедура возвращает фокус приложению?

Любая обратная связь с благодарностью. У меня такое чувство, что я правильно отношусь к функциям SQL, но не уверен на 100%.

** дополнительная информация:

  1. Выполнение кода использует [async = true] в строке подключения
  2. Для выполнения кода используется метод [SqlCommand]. [ExecuteNonQuery]

Ответы [ 6 ]

2 голосов
/ 20 июля 2009

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

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

Есть ли в строке подключения async = true? Выполняется ли SP с помощью BeginExecuteReader или Begin-что-нибудь еще?

2 голосов
/ 20 июля 2009

Как вы называете процедуру? Я собираюсь догадаться, что вы используете ExecuteNonQuery () для вызова процедуры. Попробуйте вызвать процедуру с помощью ExecuteScalar () и измените процедуру следующим образом:

ALTER PROCEDURE [dbo].[ALLOCATE_BUDGET] 
    @budget_scenario_id uniqueidentifier
AS
BEGIN
   ...

    RETURN True
END

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

2 голосов
/ 20 июля 2009

Вы также можете попробовать использовать оператор RETURN в своих дочерних хранимых процедурах, которые можно использовать для возврата кода результата обратно в родительскую процедуру. Вы можете вызвать дочернюю процедуру чем-то вроде "exec @myresultcode = BUDGET_ALLOCATE_SCENARIO_REGIONBYREGION()". Я думаю, что это должно заставить родительскую процедуру ждать завершения дочерней процедуры.

0 голосов
/ 20 июля 2009

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

И я бы не стал запускать последний процесс до тех пор, пока не проверим действительный код возврата от предыдущих процессов (это может привести к серьезным проблемам в случае смерти одного из предыдущих процессов)

Также рассмотрите, должно ли все это происходить в транзакции (эти данные изменяют данные в таблице?)

(Неужели я единственный, кому смешно, у вас есть прок, чтобы запустить процесс «Ничего не делать»?)

0 голосов
/ 20 июля 2009

Влияет ли выполнение этих вызовов на вызовы функций, как хранимая процедура возвращает фокус приложению?

номер

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

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

0 голосов
/ 20 июля 2009

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

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

...