2013-05-06 12 views
6

DOMANDA

Come accedere ai "Risultati", "Messaggi" e "Valore restituito" di una stored procedure utilizzando Entity Framework 4.4 e C# 4.0?Come accedere a "Risultati", "Messaggi" e "Valore restituito" di una stored procedure utilizzando Entity Framework 4?

Di seguito è riportata la stored procedure che accetta tre parametri. In un modo o nell'altro, quando eseguo la procedura di archiviazione, dovrei, spero, riuscire ad accedere a tutti e tre i valori per "Risultati", "Messaggi" e "Valore restituito".

Qualcuno può aiutarmi a capire come farlo con EF? Utilizzando il codice che viene generato da tutti gli obiettivi EF mi sembra di essere in grado di accedere è 'Risultati' della query (righe restituite)

stored procedure

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 

CODICE

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

Questo problema con EF non ha restituito il valore di ritorno dei processi memorizzati è stato corretto con EF 6.1.3? – Kixoka

risposta

11

Quindi, per prima cosa :-) Voglio solo assicurarci di essere sulla stessa pagina prima di rispondere alle 3 parti della domanda. EF è progettato per essere un ORM (object-relational-mapper). Ciò significa che il suo scopo è di tradurre i dati relazionali in oggetti di codice (e viceversa). Il meccanismo che usa per questo è set di risultati (non valori di ritorno). Quindi la maggior parte degli impianti idraulici all'interno di EF è specificamente progettata per operare sui set di risultati e anche per generare automaticamente SQL per ottenere questi set di risultati. Tuttavia, poiché le persone lo hanno richiesto, EF ora ha la capacità di eseguire stored procedure, ma tale capacità non è completa ed è una sorta di effetto collaterale delle principali funzionalità del prodotto. Detto questo, EF utilizza ADO.NET sotto le copertine, ed è qui che otterrete le vostre risposte perché ADO.NET gestisce tutti i vostri scenari.

Primo problema: come ottenere risultati. EF eseguirà l'SP in questo caso e, presumibilmente, è mappato su un oggetto che ha proprietà che corrispondono alle colonne del risultato. Ciò significa che EF creerà una raccolta (il risultato di una query enumerabile impostata in modo più preciso) di oggetti, ognuno dei quali rappresenta una riga di dati nei risultati. Nel tuo caso, il ritorno del tuo metodo è ObjectResult. ObjectResult è una raccolta di oggetti e ogni elemento è di tipo THIS_PROCEDURE_RESULT, che a sua volta ha una proprietà per ogni colonna mappata del risultato.

Secondo problema: come ottenere i messaggi. Se Raiserror viene utilizzato con un determinato intervallo di gravità, causerà il lancio di ADO.NET e l'eccezione (di tipo SqlException). EF passerà appena quell'errore. Quell'istanza SQLException conterrà tutte le informazioni sul messaggio di errore &. Per vederlo, basta rilevare l'errore:

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

Tuttavia, se l'istruzione RAISERROR è di un avvertimento o info gravità, ADO.NET non sarà un'eccezione. In tal caso, è necessario utilizzare un evento dell'oggetto connessione per visualizzare informazioni e messaggi di avviso dal database. Per fare ciò in EF, è necessario ottenere EntityConnection dal contesto dell'oggetto EF, quindi ottenere la connessione Store da EntityConnection. Se si utilizza SQL Server (provider ADO.NET SqlClient), questa sarà un'istanza SqlConnection. Quell'istanza contiene un evento chiamato InfoMessage. È possibile collegare un gestore di eventi a quell'evento per intercettare i messaggi. Maggiori informazioni qui: http://support.microsoft.com/kb/321903

Ultimo problema: come ottenere il valore restituito. Questo sta per succhiare. Basato sul mio primo paragrafo, EF non è realmente progettato per gestire arbitrariamente le chiamate SP. Mentre mapperà i set di risultati alle raccolte di oggetti, non gestisce i valori di ritorno dagli SP. Dovrai utilizzare ADO.NET senza il layer EF per accedere alle collezioni Parameters dell'oggetto SqlCommand.Uno dei parametri è di tipo parametro ReturnValue e conterrà il valore di ritorno stesso.

+0

Grazie per la risposta così dettagliata. Il tuo tempo è molto apprezzato. – newSingleton

Problemi correlati