T-SQL Przechwytywanie wyniku z procedury wykonywanej w innej procedurze

0

Witam
Mam dwie procedury zewnętrzną i wewnętrzną. W zewnętrznej procedurze wykonywana jest wewnętrzna procedura oraz jakiś tam select. Druga procedura wywołuje jakiś tam select i zwraca mi wartość przy wykorzystaniu słowa kluczowego return. Sytuacja wygląda mniej więcej w ten sposób jak w przedstawionych poniżej przykładowych kodach źródłowych dwóch procedur.

Procedura zewnętrzna:

 
CREATE PROCEDURE OutsideProcedure @param1 int
AS
BEGIN
-- jakis kod

DECLARE @ResultInsideProcedure int
SELECT * FROM Table
EXECUTE @ResultInsideProcedure = [dbo].[InsideProcedure]
-- @ResultInsideProcedure zwróci wartość przypisaną do returna w procedurze wewnętrznej
END

Procedura wewnętrzna:

 
CREATE PROCEDURE InsideProcedure @param1 int
AS
BEGIN
SELECT * From AnotherTable
RETURN 1

END

Po wykonaniu procedur przy wykorzystaniu np. SQL Management Studio wszystko jest ok, wyświetla mi wyniki z procedury zewnętrznej i wewnętrznej. Schody zaczynają się dalej, ponieważ procedury mapowane są do serwisu WCF przy wykorzystaniu EF w wersji 4. Beznadziejne rozwiązanie bo mapowane są tylko procedury. Siłą rzeczy EF w wersji 4 mapuje mi wyniki z jednego selecta w procedurze zewnętrznej. Ja natomiast potrzebuje przechwycić wynik z procedury wewnętrznej.

Pytanie jak to zrobić tak by **nie modyfikować procedury wewnętrznej ** ani nie stosować ADO.NET w serwisie.

Mam nadzieję, że jasno wytłumaczyłem problem.

0

Ale to nie możesz z EF po prostu wywołać tej wewnętrznej procedury?

0
somekind napisał(a):

Ale to nie możesz z EF po prostu wywołać tej wewnętrznej procedury?

Teoretycznie tak, ale w tej zewnętrznej procedurze są wykonywane operacje (update) w ramach transakcji. Dopiero wykonanie wewnętrznej procedury w procedurze zewnętrznej po tych operacjach w ramach transakcji wyrzuca mi to co chce. Jeżeli wywołam samą procedurę wewnętrzną nie otrzymam żądanego efektu. Wiem rozwiązanie tutaj jest bardzo chaotyczne.

0

A jakby podejść w ten sposób:

CREATE PROCEDURE OutsideProcedure @param1 INT
AS
BEGIN
-- jakis kod
 
DECLARE @ResultInsideProcedure INT
EXECUTE @ResultInsideProcedure = [dbo].[InsideProcedure]
SELECT *,@ResultInsideProcedure as [ResultInsideProcedure] FROM TABLE

-- @ResultInsideProcedure zwróci wartość przypisaną do returna w procedurze wewnętrznej
END
0
Panczo napisał(a):

A jakby podejść w ten sposób:

CREATE PROCEDURE OutsideProcedure @param1 INT
AS
BEGIN
-- jakis kod
 
DECLARE @ResultInsideProcedure INT
EXECUTE @ResultInsideProcedure = [dbo].[InsideProcedure]
SELECT *,@ResultInsideProcedure as [ResultInsideProcedure] FROM TABLE

-- @ResultInsideProcedure zwróci wartość przypisaną do returna w procedurze wewnętrznej
END

Nie wiem czy dobrze wytłumaczyłem. Twój kod zwróci mi rezultat z zewnętrznej procedury + return z wewnętrznej, ale ja chciałbym przechwycić całe zapytanie SELECT z wewnętrznej. Problem leży też tutaj, że ona ma na siłę przypisanego returna. Przy tym jest problem. Czyli chciałbym rezultat z zapytania w wewnętrznej procedurze przechwycić oprócz wartości zwracanej przy wykorzystaniu returna.

1

EF 4 nie pozwala o ile mi wiadomo na zwrócenie więcej niż jeden z SELECT z procedury składowanej. Tutaj jest artykuł o tym gdzie napisano, że przed EF 5 takiej możliwości nie ma.
https://msdn.microsoft.com/en-us/data/jj691402.aspx

1

Nie wiem co to EF, ale czy możesz skorzystać z tabeli tymczasowej tudzież zmiennej tabelarycznej w procedurze zewnętrznej i w wewnętrznej ładować dane do tabeli tym? Musiałbyś zapewne zmienić logikę procedury zewnętrznej, aby bazować na danych z tabeli czyli np zrobić select w zewnętrznej tak jak jest obecnie + select z tabeli tym po wykonaniu procedury wewnętrznej?

Czyli mniej więcej tak:

 CREATE PROCEDURE OutsideProcedure @param1 INT
AS
BEGIN
-- jakis kod
 
DECLARE @ResultInsideProcedure INT
SELECT * FROM TABLE
CREATE TABLE #Nazwa (-definicja tabeli-)
EXECUTE @ResultInsideProcedure = [dbo].[InsideProcedure]
-- @ResultInsideProcedure zwróci wartość przypisaną do returna w procedurze wewnętrznej
-- SELECT * FROM #Nazwa
END

CREATE PROCEDURE InsideProcedure @param1 INT
AS
BEGIN
INSERT INTO #Nazwa 
SELECT * FROM AnotherTable
-- Ewentualnie tu select jeśli musi być
RETURN 1
 
END

Wtedy procedura nadrzędnia zwróci wyniki z dwóch tabel (zew i wew). Ewentualnie procedura zew może mieć parametr aby działać tak jak obecnie + drugi parametr który zwróci tylko dane z wewnętrznej procedury.

1

W zewnętrznej procedurze:

 
declare @temp_table table
(
	--kolumny tak jak w tej AnotherTable w wewn. procedurze
)

insert into @temp_table exec InsideProcedure @param1

I potem dodaj do rezultatu w zewn. procedurze. Czyli o to chyba koledze wyżej chodziło. Bo wpadł chyba na ten sam pomysł co ja.

2
a.dudek76 napisał(a):

Teoretycznie tak, ale w tej zewnętrznej procedurze są wykonywane operacje (update) w ramach transakcji. Dopiero wykonanie wewnętrznej procedury w procedurze zewnętrznej po tych operacjach w ramach transakcji wyrzuca mi to co chce. Jeżeli wywołam samą procedurę wewnętrzną nie otrzymam żądanego efektu. Wiem rozwiązanie tutaj jest bardzo chaotyczne.

Entity Framework to abstrakcja nad bazą danych, jaki sens miałaby abstrakcja, która dopuszcza Cię do szczegółów implementacji? EF nic nie wie o tym, że wewnątrz jest jakaś procedura - on wie tylko o zewnętrznej procedurze, jej parametrach i zwracanym wyniku.
Jeśli chcesz się dobrać przez EF do wewnętrznej procedury, to musisz ją wywołać niezależnie. Jeśli przed jej wywołaniem potrzeba zrobić jakiś update, to musisz to zrobić z poziomu EF.
Alternatywnie, możesz napisać drugą wersję procedury zewnętrznej, która zrobi potrzebne update, wywoła wewnętrzną, a potem zwróci jej wynik.

Ot, uroki zaszywania logiki w bazie danych.

1 użytkowników online, w tym zalogowanych: 0, gości: 1