2013-05-06 7 views
6

PYTANIE:

Jak uzyskać dostęp do "Wyniki", "Wiadomości" i "Zwrot wartości" procedury składowanej za pomocą Entity Framework 4.4 i C# 4.0?Jak uzyskać dostęp do "Wyniki", "Wiadomości" i "Zwrócić wartość" przechowywanej procedury za pomocą Entity Framework 4?

Poniżej znajduje się procedura składowana, która pobiera trzy parametry. Tak czy inaczej, kiedy uruchamiam procedurę sklepu, mam nadzieję, że będę miał dostęp do wszystkich trzech wartości dla "wyników", "wiadomości" i "wartości zwrotu".

Czy ktoś może mi pomóc dowiedzieć się, jak to zrobić z EF? Za pomocą kodu, który jest generowany z EF wszystkim wydaje mi się, aby mieć dostęp jest „Wyniki” zapytania (zwróconych wierszy)

procedury przechowywanej

USE [THIS_DB] 
GO 

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 

ALTER PROCEDURE [dbo].[THIS_PROCEDURE] 
    @FIRST_PARAM CHAR(17) = NULL, 
    @SECOND_PARAM CHAR(2) = NULL, 
    @THIRD_PARAM CHAR(5) = NULL 
AS 
BEGIN 
    SET NOCOUNT ON; 
    DECLARE @ReturnValue INT = 0; 
    IF COALESCE(@SECOND_PARAM, 'XX') NOT IN ('XX', 'YY') 
    BEGIN 
     RAISERROR('Invalid @SECOND_PARAM value: %s; @SECOND_PARAM mXXt be XX or YY.', 2, 1, @SECOND_PARAM) WITH SETERROR; 
     SET @ReturnValue = -50100; 
    END 
    IF COALESCE(@SECOND_PARAM, 'XX') = 'YY' 
    BEGIN 
     RAISERROR('@SECOND_PARAM value: %s; YY is valid, but currently is not supported, returning XX results.', 2, 1, @SECOND_PARAM) WITH SETERROR; 
     SET @ReturnValue = -50105; 
    END 
    IF COALESCE(@THIRD_PARAM, 'XX-EN') NOT IN ('XX-EN') 
    BEGIN 
     RAISERROR('Invalid @THIRD_PARAM value: %s; @THIRD_PARAM mXXt be XX-EN.', 2, 1, @THIRD_PARAM) WITH SETERROR; 
     SET @ReturnValue = -50101; 
    END 
    SELECT DISTINCT 
     THESE.VALUES 
     FROM dbo.THIS_TABLE 
     WHERE THESE.CONDITIONS; 

    IF @@ROWCOUNT = 0 
    BEGIN 
     DECLARE @SP_MATCHCOUNT INT 

     EXEC @SP_MATCHCOUNT = [dbo].[MATCHTABLE] @PATTERNH = @PATTERN 
     IF @SP_MATCHCOUNT > 0 
     BEGIN 
      RAISERROR('Mapping from HERE to HERE not found for PATTERN: %s.', 2, 1, @PATTERN) WITH SETERROR 
      SET @ReturnValue = -50103; 
     END 
     ELSE 
     BEGIN 
      RAISERROR('PATTERN Pattern not found for PATTERN: %s.', 2, 1, @PATTERN) WITH SETERROR 
      SET @ReturnValue = -50104; 
     END 
    END 
    RETURN @ReturnValue 
END 

KOD

public virtual ObjectResult<THIS_PROCEDURE_RESULT> THIS_PROCEDURE_METHOD(string FIRST, string SECOND, string THIRD) 
{ 
    var FIRST_PARAM = FIRST != null ? 
     new ObjectParameter("FIRST", FIRST) : 
     new ObjectParameter("FIRST", typeof(string)); 

    var SECOND_PARAM = SECOND != null ? 
     new ObjectParameter("SECOND", SECOND) : 
     new ObjectParameter("SECOND", typeof(string)); 

    var THIRD_PARAM = THIRD != null ? 
     new ObjectParameter("THIRD", THIRD) : 
     new ObjectParameter("THIRD", typeof(string)); 

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<THIS_PROCEDURE_RESULT>("THIS_PROCEDURE", FIRST_PARAM, SECOND_PARAM, THIRD_PARAM); 
} 
+0

Czy ten problem z EF nie zwracającymi zapisanych wartości zwracanych proc został naprawiony w EF 6.1.3? – Kixoka

Odpowiedz

11

Przede wszystkim :-) Po prostu chcę się upewnić, że jesteśmy na tej samej stronie, zanim odpowiem na 3 części pytania. EF jest zaprojektowany jako ORM (obiektowo-relacyjny-mapper). Oznacza to, że jego celem jest tłumaczenie danych relacyjnych na obiekty kodu (i odwrotnie). Mechanizm, którego używa, to zestawy wyników (nie wartości zwracane). Tak więc większość instalacji wewnątrz EF jest specjalnie zaprojektowana do działania na zestawach wyników, a także do automatycznego generowania kodu SQL w celu uzyskania tych zestawów wyników. Ponieważ jednak użytkownicy tego zażądali, EF ma teraz możliwość wykonywania procedur przechowywanych, ale ta zdolność nie jest kompleksowa i jest pewnego rodzaju efektem ubocznym głównych możliwości produktu. Powiedziawszy to, EF używa ADO.NET pod okładkami i właśnie tam dostaniesz odpowiedzi, ponieważ ADO.NET obsługuje wszystkie twoje scenariusze.

Pierwszy problem - jak uzyskać wyniki. EF wykona SP w tym przypadku, i przypuszczalnie jest zmapowany do jakiegoś obiektu, który ma właściwości pasujące do kolumn wyników. Oznacza to, że EF utworzy kolekcję (przeliczalne wyniki zapytania dla większej dokładności) obiektów, z których każdy reprezentuje rząd danych w wynikach. W twoim przypadku zwrotem twojej metody jest ObjectResult. ObjectResult to kolekcja obiektów, a każdy element jest typu THIS_PROCEDURE_RESULT, który z kolei ma właściwość dla każdej odwzorowanej kolumny wyniku.

Drugi problem - jak zdobyć wiadomości. Jeśli Raiserror zostanie użyty z pewnym zakresem istotności, spowoduje to, że ADO.NET rzuci i wyjdzie (typ SqlException). EF po prostu wyprowadzi (przejdzie) ten błąd. Ta instancja klasy SQLException będzie zawierała wszystkie informacje o błędzie: &. Aby go zobaczyć, wystarczy złapać błąd:

try 
{ 
    // call EF SP method here... 
} 
catch(SqlException se) 
{ 
    Debug.WriteLine(se.Message); 
} 
catch(Exception e) 
{ 
    // all non-DB errors will be seen here... 
} 

Jeżeli jednak oświadczenie RAISERROR jest ostrzeżenie lub informacji ciężkości, ADO.NET nie wyjątek. W takim przypadku należy użyć zdarzenia obiektu połączenia, aby wyświetlić informacje i komunikaty ostrzegawcze z bazy danych. Aby to zrobić w EF, musisz uzyskać EntityConnection z kontekstu obiektu EF, a następnie pobrać połączenie Store z EntityConnection. Jeśli używasz programu SQL Server (dostawca ADO.NET SqlClient), będzie to instancja SqlConnection. Ta instancja zawiera zdarzenie o nazwie InfoMessage. Możesz podpiąć procedurę obsługi zdarzeń do tego zdarzenia, aby pułapkować wiadomości. Więcej informacji: http://support.microsoft.com/kb/321903

Ostatni problem - jak uzyskać zwrot. Ten będzie ssał. Na podstawie mojego pierwszego akapitu, EF nie jest tak naprawdę zaprojektowany, aby arbitralnie obsługiwać połączenia SP. Chociaż mapuje zestawy wyników do kolekcji obiektów, nie obsługuje wartości zwracanych z SP. Będziesz musiał użyć ADO.NET bez warstwy EF, aby uzyskać dostęp do kolekcji Parameters obiektu SqlCommand.Jednym z parametrów jest parametr ReturnValue typu parameter i będzie on zawierał samą wartość zwracaną.

+0

Dziękuję za tak szczegółową odpowiedź. Twój czas jest bardzo cenny. – newSingleton

Powiązane problemy