4 messaggi dal 26 ottobre 2006
Vengo subito alla domanda:
Ho la seguente SP:

CREATE PROCEDURE Localitacode2
@LocalitaCode int,
@NumRowsChanged int output
AS
BEGIN
SET NOCOUNT ON;
SELECT sg.IdOS, sg.nomeProdotto, sg.Costo, sg.anno, sg.Data, sg.Localita, loc.descLocalita AS MM from dbo.SistemiGastronomici sg
inner join dbo.Localita as loc on loc.IdLocalita = sg.LocalitaConvention
where sg.LocalitaConvention= @LocalitaCode;

set @NumRowsChanged = @@ROWCOUNT // Funziona
--set @NumRowsChanged = (select count(*) from MM) // Funziona
END

Se da Visual Studio o Management Studio eseguo la seguente query:
DECLARE @t1 int
DECLARE @t2 int
exec Localitacode2 5, @t2 OUTPUT
print 'CI SONO REgooCORDS????'
if (@t2 = 0)
print 'NON CI SONO RECORDS'
else
print convert(VARCHAR, @t2 ) + ' sono stati trovati'

Funziona tutto correttamente. Sia la tabella con i records sia il valore del parametro @t2 vengono restituiti.
Se adesso eseguo da Visual Studio la seguente:

private void button1_Click(object sender, EventArgs e)
{
using (SqlConnection conn = new SqlConnection(@"Data Source = (LocalDB)\MSSQLLocalDB; AttachDbFilename=D:\Visual_2017\dbTest2\dbTest2\SistemiOp.mdf;Integrated Security = True"))
{
using (SqlCommand cmd = new SqlCommand("Localitacode2", conn))
{
cmd.CommandType = CommandType.StoredProcedure;

SqlParameter sqlParameter = new SqlParameter("@LocalitaCode", SqlDbType.Int);
sqlParameter.Direction = ParameterDirection.Input;
sqlParameter.Value = 5;

SqlParameter sqlParameter1 = new SqlParameter("@NumRowsChanged", SqlDbType.Int);
sqlParameter1.Direction = ParameterDirection.Output;
// sqlParameter1.Value = 0;

cmd.Parameters.Add(sqlParameter);
cmd.Parameters.Add(sqlParameter1);
cmd.Parameters.Add(sqlParameter2);
SqlDataReader estrakt;

try
{
conn.Open();
if (conn.State == ConnectionState.Open)
estrakt = cmd.ExecuteReader();
} catch (SqlException ex)
{
throw ex;
}

Int32 ret = Convert.ToInt32(cmd.Parameters["@NumRowsChanged"].Value);

conn.Close();
}
}
}

La tabella viene restituita il parametro invece NO. Ho cercato invano in rete una qualche giustificazione ma non l'ho trovata. Qualcuno sa spiegarmi dove sbaglio.
Ringrazio tutti per l'attenzione.
Paolo
11.861 messaggi dal 09 febbraio 2002
Contributi
Ciao Paolo,
dovresti prima chiudere il data reader e POI leggere il parametro in output.
Per chiuderlo o invochi estrakt.Close oppure (meglio) lo fai con un blocco using.
Esempio:
try
{
  conn.Open();
  if (conn.State == ConnectionState.Open)
  {
    using (SqlDataReader estrakt = cmd.ExecuteReader())
    {
      //Qui fai qualcosa con il data reader
    }
    //Ora puoi leggere il parametro in output perché il datareader è stato ormai chiuso
    Int32 ret = Convert.ToInt32(cmd.Parameters["@NumRowsChanged"].Value);
  }
}
catch (SqlException ex)
{ 
  throw ex; //Perché catturi l'eccezione e la rilanci subito senza fare nient'altro?
}


ciao,
Moreno
Modificato da BrightSoul il 12 luglio 2019 16:09 -

Enjoy learning and just keep making
4 messaggi dal 26 ottobre 2006
Grazie Moreno per l'aiuto.
Adesso funziona. Non mi é chiaro perché l'SqlDataReader interferisce, non ho avuto il tempo di cercare la causa. Ma di tutti gli articoli che ho letto in italiano, in inglese e tedesco nessuno ha fatto cenno l'SqlDataReader come causa del problema.
Ancora Grazie.
Paolo
11.861 messaggi dal 09 febbraio 2002
Contributi
Ciao, prego.
Guarda, io non sono un esperto di SQL Server quindi ti posso dare solo la mia opinione non informata:
presumo che il protocollo di comunicazione con SQL Server preveda che per primi siano restituiti i risultati tabellari (il "resultset") e poi, una volta concluso l'invio di questi, il server si metta a disposizione per inviare i valori dei parametri di output.

Invocando il metodo .Close del datareader (esplicitamente o implicitamente con il blocco using) tu, come client, dichiari che hai finito la lettura del resultset e quindi il server ti può dare i valori dei parametri di output.

Non sono riuscito a trovare questa cosa nella documentazione. Ho trovato solo questo commento di un ex membro del team di sviluppo di SQL Server:
https://stackoverflow.com/questions/1682827/accessing-output-parameters-before-processing-result-set-in-sql-server-via-jdbc/1684906#1684906

Forse Andrea Montanari ci può aiutare a trovare una fonte "ufficiale".

ciao,
Moreno
Modificato da BrightSoul il 12 luglio 2019 22:27 -

Enjoy learning and just keep making
salve a tutti,
e "io non sono ufficiale" :D
comunque secondo me Moreno ci ha preso, in quanto il Reader, per definizione, "va consumato" altrimenti resta bloccante per altre operazioni... il concetto di base e' alla stregua del "cursore firehose" vero e proprio di SQL Server, che e' un datapump continuo che "va consumato" e chiuso il prima possibile... sinceramente non ho mai guardato che lock imposti un Reader, tecnicamente dovrebbe usarne di "sola lettura" e congrui con l'isolation level impostato, ma il ragionamento di Moreno ha piu' che senso, tanto piu' che l'output resterebbe circoscritto all'interno di SQL Server se non fino alla "fine" dell'esecuzione della procedura->legata al reader, che una volta consumato in toto puo' restituire i parametri aggiornati...
questo ultima parte mi pare di averla letta su Ado.Net di Sheppa, ma non ricordo bene dove, quindi "cum granu salis" :D:D
pero' tendenzialmente sono concorde (senza prova alcuna) con Moreno :D
salutissimi omnia
--
Andrea

Andrea Montanari
http://www.hotelsole.com - http://www.hotelsole.com/asql/index.php

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.