Hoje, uma consulta precisa retornar um conjunto de resultados através do ExcuteReader e, ao mesmo tempo, deseja gerar parâmetros. No início, não consegui obter o valor dos parâmetros de saída, pensando que o procedimento armazenado apresentava um erro. o teste no analisador de consulta estava correto e os parâmetros de saída foram realmente alterados.
O que é ainda mais intrigante é que depois de lançar uma exceção durante a conversão de tipo forçada da saída, ela pode realmente ser obtida novamente. É impossível imaginar uma página assim. API comumente usada para aparecer. Isso está errado? Meu código é semelhante ao seguinte cenário:
tente {
usando (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
int val = (int)cmd.Parameters[1].Value; // Ainda vazio agora
// mais
}
}
catch(Exceção exp) {
throw new ApplicationException("Valor do parâmetro de saída: " + cmd.Parameters[1].Value, exp);
}
É realmente frustrante depois de depurar e rastrear por uma hora,
finalmente encontrei a resposta no MSDN:
Ao usar um objeto Command com um procedimento armazenado, você pode definir a propriedade CommandType do objeto Command como StoredProcedure. Quando CommandType for StoredProcedure, você poderá usar a propriedade Parameters do Command para acessar parâmetros de entrada e saída e valores de retorno. Independentemente de qual método Execute seja chamado, a propriedade Parameters pode ser acessada. Entretanto, quando ExecuteReader é chamado, o valor de retorno e os parâmetros de saída não estarão acessíveis até que o DataReader seja fechado.
ref: http://msdn2.microsoft.com/zh-CN/library/tyy0sz6b.aspx
É isso, sinto que fui enganado pela MS novamente, por que sou inexperiente em aprender? Já alterei o documento e
retornei a ele. Seu próprio ambiente de código ainda pode ser explicado.
Porque quando a exceção é capturada, o escopo de uso foi saltado, o DataReader foi fechado automaticamente e o valor do parâmetro de saída pode ser obtido naturalmente.
Claro que se você colocar o try catch no using, ainda não conseguirá, pois ele ainda está no escopo using e o DataReader não foi fechado.
Além disso, o MSDN diz que só pode ser acessado se o DataReader estiver fechado, mas não é o caso.
Após o teste, pode ser resumido da seguinte forma:
1. Para ExecuteReader, Output parm e returnvalue são retornados ao DataReader como um conjunto de resultados, e o conjunto de resultados é sempre o último.
2. De acordo com 1, quando há um conjunto de resultados, para acessar os parâmetros de saída e valores de retorno, é necessário chamar NextResult para o local do conjunto de resultados correspondente aos parâmetros de saída e valores de retorno.
3. De acordo com 1, quando Execute não retorna um conjunto de resultados, ele pode ser acessado diretamente (observe que não há necessidade de chamar Read())
4. Preste atenção especial à necessidade de chamar NextResult várias vezes se vários conjuntos de resultados forem retornados; se o número de conjuntos de resultados for dinâmico, o valor de retorno de nextResult() será falso;
5. Mesmo que a opção CommandBehavior.SingleResult seja especificada para ExecuteReader (retornando um único conjunto de resultados, na verdade, retornando o primeiro conjunto de resultados do lote), os parâmetros de saída serão retornados como um conjunto de resultados.
6. Ao fechar o DataReader (Close()), os parâmetros de saída são preenchidos e portanto acessíveis.
7. Como o DataReader é somente leitura direta, mesmo que os parâmetros de saída sejam obtidos através do método NextResult antes de fechar o DataReader, o conjunto de resultados anterior não pode mais ser acessado (em alguns casos, você pode querer controlar dinamicamente o conjunto de resultados através da saída parâmetros visita).
8. Para resolver o problema em 6, você não pode usar o parâmetro de saída e retornar diretamente o parâmetro de saída como o primeiro resultado (SELECT @parmname).
O acima é apenas meu próprio resumo, espero que não haja discrepância e pode ser. útil para iniciantes.
referência:
http://www.bigcircleboy.net/583a194f-2c2c-4662-9036-4e2f0eb262396084313157728108.html