【问题标题】:Calling stored procedure from C# is not working从 C# 调用存储过程不起作用
【发布时间】:2023-03-11 15:34:01
【问题描述】:

我在 SQL Server 2008 中创建了一个过程:

CREATE PROCEDURE USP_VISUALIZAR_PIS_PROCESSO_IMPORTACAO_DETALHE_HISTORICO
@DATA_HISTORICO DATETIME
, @SIGLA_ESTADO VARCHAR(2)
, @ANO_MES INT
, @SEMANA_MES INT   
, @CODIGO_LINHA_FICTICIA INT
AS
BEGIN

SELECT  P.PROD_CD_PRODUTO
        , P.PROD_DS_PRODUTO
        , HIST.PIDH_DT_NOTA_FISCAL
        , HIST.PIDH_NR_ORDEM
        , HIST.PIDH_NR_ITEM
        , HIST.PIDH_CD_PROCESSO
        , HIST.PIDH_DT_PREV_BOOKING
        , HIST.PIDH_DT_CHEGADA_PORTO
        , HIST.PIDH_DT_PREVISAO_EMBARQUE_ORDEM
        , HIST.PIDH_DT_LIBERACAO
        , ISNULL(HIST.PIDH_DS_CANAL, '-') AS PIDH_DS_CANAL
        , HIST.PIDH_CD_REFERENCIA
        , HIST.PIDH_CD_REMESSA
        , HIST.PIDH_IN_FATURAS_IMPORTACAO
        , HIST.PIDH_NM_FORNECEDOR
        , CASE WHEN HIST.PIDH_DT_NOTA_FISCAL IS NOT NULL THEN 'Sim' ELSE 'NãO' END AS INDICADOR_RECEBIDO
        , SUM(HIST.PIDH_QN_FATURA) AS PIDH_QN_FATURA
        , MAX(HIST.PIDH_QN_ORDEM) AS PIDH_QN_ORDEM
        , MAX(HIST.PIDH_QN_DIAS_DEMURRAGE) AS PIDH_QN_DIAS_DEMURRAGE
        , CASE WHEN HIST.PIDH_DT_LIBERACAO IS NOT NULL THEN 1 ELSE 0 END AS LIBERADO
        , HIST.PIDH_DT_HISTORICO
        , HIST.DDT_NR_SEMANA_MES
        , HIST.DDT_NR_ANOMES
  FROM  PROCESSO_IMPORTACAO_DETALHE_HISTORICO HIST
        INNER JOIN ESTADO E ON E.ESTA_CD_ESTADO = HIST.ESTA_CD_ESTADO
        INNER JOIN PRODUTO P ON P.PROD_CD_PRODUTO = HIST.PROD_CD_PRODUTO
        INNER JOIN LINHA L ON L.LINH_CD_LINHA = P.LINH_CD_LINHA
        INNER JOIN LINHA_FICTICIA LF ON LF.LIFI_CD_LINHA_FICTICIA = L.LIFI_CD_LINHA_FICTICIA
        INNER JOIN VOLTAGEM V ON V.VOLT_CD_VOLTAGEM = P.VOLT_CD_VOLTAGEM
        INNER JOIN PRODUTO_COMERCIAL PC ON PC.PRCO_CD_PRODUTO_COMERCIAL = P.PRCO_CD_PRODUTO_COMERCIAL   
 WHERE  HIST.PIDH_DT_HISTORICO = @DATA_HISTORICO
  GROUP BY  P.PROD_CD_PRODUTO
        , P.PROD_DS_PRODUTO
        , HIST.PIDH_DT_NOTA_FISCAL
        , HIST.PIDH_NR_ORDEM
        , HIST.PIDH_NR_ITEM
        , HIST.PIDH_CD_PROCESSO
        , HIST.PIDH_DT_PREV_BOOKING
        , HIST.PIDH_DT_CHEGADA_PORTO
        , HIST.PIDH_DT_PREVISAO_EMBARQUE_ORDEM
        , HIST.PIDH_DT_LIBERACAO
        , HIST.PIDH_DS_CANAL
        , HIST.PIDH_CD_REFERENCIA
        , HIST.PIDH_CD_REMESSA
        , HIST.PIDH_IN_FATURAS_IMPORTACAO
        , HIST.PIDH_NM_FORNECEDOR
        , HIST.PIDH_DT_HISTORICO
        , HIST.DDT_NR_SEMANA_MES
        , HIST.DDT_NR_ANOMES
END

当我从 SQL Server Management Studio 调用时,此过程工作正常,但当我从 C# 调用时,它不起作用。我需要这个过程的输出,但我没有成功。

C#代码是这样的:

object[] o = new object[5];
o[0] = dataHistorico;
        o[1] = filtro.SiglaEstado;
        o[2] = filtro.AnoMes;
        o[3] = filtro.SemanaMes;
        o[4] = linhaFiciticia;

string query = "exec USP_VISUALIZAR_PIS_PROCESSO_IMPORTACAO_DETALHE_HISTORICO @DATA_HISTORICO = {0}, @SIGLA_ESTADO = {1}, @ANO_MES = {2}, @SEMANA_MES = {3}, @CODIGO_LINHA_FICTICIA = {4}";
var r = db.Database.ExecuteSqlCommand(query, o);

这段代码的输出总是-1,但是当我从 SQL Server 执行时,它返回了超过 10,000 条记录。

怎么了?有人可以帮我解决这个问题吗?

更新

解决办法如下:

        string query = "exec USP_VISUALIZAR_PIS_PROCESSO_IMPORTACAO_DETALHE_HISTORICO";
        string connectionString = System.Configuration.ConfigurationSettings.AppSettings["StringConexao"].ToString();

        SqlConnection conn = new SqlConnection(connectionString);            
        SqlCommand command = new SqlCommand(query + " @DATA_HISTORICO = '" + dataHistorico.ToString("yyyy-MM-dd") + "', @SIGLA_ESTADO = " + filtro.SiglaEstado + ", @ANO_MES = " + filtro.AnoMes + ", @SEMANA_MES = " + filtro.SemanaMes + ", @CODIGO_LINHA_FICTICIA = " + linhaFiciticia, conn);

        command.Connection.Open();
        SqlDataAdapter sda = new SqlDataAdapter(command);
        command.Connection.Close();

        DataTable dt = new DataTable();
        sda.Fill(dt);

        conn.Close();

        command.Connection.Close();

        foreach (DataRow row in dt.Rows)
        {
            ProcessoImportacaoDetalhePISVO pi = new ProcessoImportacaoDetalhePISVO();

            string processo = row["PIDH_CD_PROCESSO"].ToString();
            string referencia = row["PIDH_CD_REFERENCIA"].ToString();

            pi.Processo = !String.IsNullOrEmpty(processo) ? processo : referencia;
            lista.Add(pi);
        }

谢谢大家的帮助!

【问题讨论】:

  • db.Database.ExecuteSqlCommand 是做什么的?
  • 你试过单独传递参数吗? db.Database.ExecuteSqlCommand(query, dataHistorico, filtro.SiglaEstado, ...)
  • 如果你使用存储过程,为什么不使用SqlCommand和SqlDataAdapter?
  • @wudzik 是的,我试过了!
  • 我要做的第一件事是对数据库运行 SQL Server Profiler,以准确查看存储过程是如何执行的。我的猜测是日期参数有问题。

标签: c# linq sql-server-2008 c#-4.0 stored-procedures


【解决方案1】:

您绝对应该在存储过程中使用 SqlCommand。试试这样的。

string connectionString = "your connection string";
    using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();
            using (SqlCommand command = new SqlCommand("USP_VISUALIZAR_PIS_PROCESSO_IMPORTACAO_DETALHE_HISTORICO", connection))
            {
                command.CommandTimeout = 0;
                command.CommandType = System.Data.CommandType.StoredProcedure;

                SqlParameter p1 = command.Parameters.Add("@DATA_HISTORICO", SqlDbType.DateTime);
                p1.Direction = ParameterDirection.Input;
                p1.Value = dataHistorico;

                SqlParameter p2 = command.Parameters.Add("@SIGLA_ESTADO", SqlDbType.VarChar);
                p2.Direction = ParameterDirection.Input;
                p2.Value = filtro.SiglaEstado;

                //.... continue for rest of parameters

                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {

                        //Read your values into some data structure
                    }
                }
            }
        }

【讨论】:

  • 感谢您的帮助。我使用了这个想法,但我以不同的方式做到了。我会用解决方案更新我的帖子。
【解决方案2】:

问题在于ExecuteSqlCommand 只返回 SQL Server 返回的内容。如果您想要返回的行数,那么您可以通过将行数选择到 SP 中的局部变量并从存储过程中返回来完成此操作。

如果您的目标是从 SP 获取记录,那么您需要探索数据库 SqlQuery 方法并查看哪些重载适用于您的情况。

【讨论】:

    【解决方案3】:

    ExecuteSqlCommand 用于执行“命令”——在 ADO.NET 中它不返回结果集(这些称为“查询”)。由于您使用的是实体框架,因此您可以在设计器中对其进行建模或使用 SqlQuery 方法。

    【讨论】:

      猜你喜欢
      • 2017-03-28
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多