2009-07-20 3 views
1

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

В настоящее время приложение разработано, оно вызывает хранимую процедуру, а затем перезагружает пользовательский интерфейс новым набором данных. Разумеется, данные, которые мы хотим отобразить, все еще обрабатываются на стороне сервера 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 UI, перед курсорами в ветвящихся вызовах будут завершены, это целесообразно для преобразования этих хранимых процедур в функции с возвращаемыми значениями? Будет ли это заставить SQL ждать до завершения основного вызова хранимой процедуры [ALLOCATED_BUDGET]?

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

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

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

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

ответ

2

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

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

    RETURN True 
END 

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

+0

Исполняющий код использует метод [SqlCommand]. [ExecuteNonQuery] – D3vtr0n

0

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

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

+0

это звучит как Waaaay слишком много доступ к данным продолжается, по моим вкусам. – D3vtr0n

2

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

+0

, так что это не имеет значения, если это хранимая процедура, а не функция? функция по определению RETURNS A VALUE. не безопаснее ли их выполнять? Я хочу проверить возвращаемое значение, чтобы убедиться, что он был успешным, а затем обновить мой сценарий_стату. спасибо за помощь. – D3vtr0n

+1

Это зависит от вас, выполняете ли вы их функции или хранимые процедуры. Просто имейте в виду, что функции имеют намного больше ограничений на то, что они могут делать по сравнению с хранимыми процедурами, например, вы не можете иметь в них инструкции обновления. Подробнее см. В этой статье: http://msdn.microsoft.com/en-us/library/ms187650.aspx. Вам может быть проще просто хранить их как хранимые процедуры. – tbreffni

+0

Хорошая точка. Спасибо, что указали это. – D3vtr0n

0

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

No.

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

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

+0

Согласен, я предпочитаю писать приложения с одним подключением к базе данных (singleton). проблема в том, что я не писал ни одного из этого кода. этот код был построен более 4 лет, а затем отложен. теперь он вернулся как плохой фильм ужасов. Моя идея использования функций будет заключаться в том, что функции возвращают значение по определению. Хранимая процедура выше не разрешает разветвление или дальнейшую обработку (например, последний элемент EXEC в хранимой процедуре выше) до тех пор, пока это значение функции не будет возвращено. или я ошибаюсь? – D3vtr0n

+1

НАЧАТЬ СДЕЛКУ? –

2

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

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

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

+0

Я добавил [async = true] в строку соединения, но все равно получаю одинаковые проблемные результаты. Он выполняется с помощью объекта SQL Command и метода ExecuteNonQuery. – D3vtr0n

+1

Я не упоминал async = true, потому что думал, что это поможет. Если вы не вызываете методы Begin *, то это не влияет. Я по-прежнему не считаю, что ваша проблема в том, что SP продолжает выполнять после возврата. Что-то еще происходит. –

+0

Ну, очевидно, это курсоры в детских процедурах. Они работают, как фоновый процесс, в то время как пользовательский интерфейс обновляется. Мне нужен лучший контроль над потоком моих SQL-запросов. Эта вещь - беспорядок, но я в опасности. Спасибо за ваш вклад. – D3vtr0n

0

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

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

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

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

+0

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

+0

Я не могу рекомендовать что-либо вместо курсоров, пока я не знаю, что они делают. Способ замены курсора на основе набора зависит от задачи, которую выполняет курсор. И не все курсоры можно заменить, но, возможно, более 90% из них могут быть. – HLGEM

Смежные вопросы