将 xml 作为参数传递给 SQL Server 中的存储过程

Posted

技术标签:

【中文标题】将 xml 作为参数传递给 SQL Server 中的存储过程【英文标题】:Pass xml as a parameter to a stored procedure in SQL Server 【发布时间】:2014-07-30 20:38:29 【问题描述】:

我正在尝试将 XML 参数从 C# 代码传递到 SQL Server 中的存储过程,但它不起作用。

public static void SaveReceiptTrans(string pSiteCode, string xml)

        try
        
            string DBKey = "sn";
            string ConnStr = Encryption.DecryptString(ConfigurationManager.ConnectionStrings[DBKey].ConnectionString);
            string CmdStr = "prc_pt_Fac_iu";

            SqlParameter[] SqlParams = new SqlParameter[1];

            SqlParams[0]            = new SqlParameter("@pReceiptsWithFactoryNameCode", SqlDbType.Xml);
            SqlParams[0].Direction  = ParameterDirection.Input;
            SqlParams[0].Value      = xml;

            int i = SqlHelper.ExecuteNonQuery(ConnStr, CommandType.StoredProcedure, CmdStr, SqlParams);
        
        catch (Exception ex)
        
            UtilLogging.LogException(ex, "Error From -> ", pSiteCode);
        
    

但是没有通过存储过程对表进行任何操作,就好像没有对存储过程进行调用一样。我已经用虚拟 xml 字符串测试了存储过程,它工作正常,但是当从 c# 代码传递参数时它不起作用。

ALTER PROCEDURE [dbo].[prc_pt_Fac_iu]
(
    @pReceiptsWithFactoryNameCode XML
)
BEGIN
   SET NOCOUNT ON

   BEGIN TRY    
      DECLARE @MAXTRANSID INT, @MAXMOVEID INT, @ROWCOUNT INT, @NEXTTRANSID INT, @NEXTMOVEID INT
      DECLARE @IDOC INT
      DECLARE @TEMPCOUNT INT, @INTFLAG INT

      SELECT 
         IDENTITY(INT) AS id, 
         line.item.value('@site_cde', 'char(8)') AS site_cde,  
         line.item.value('@po_nbr', 'char(17)') AS po_nbr,  
         line.item.value('@po_line_nbr', 'smallint') AS po_line_nbr, 
         line.item.value('@ran', 'int') AS ran, 
         line.item.value('@factory_name_code', 'int') AS factory_name_code, 
         NULL AS item_id, 
         NULL AS qty,
         NULL AS cur_loc_id,
         NULL AS cur_loc_status,
         NULL AS trans_id,
         NULL AS [user_id]
      INTO 
         #tmpReceiptsWithFactoryNameCode  
      FROM 
         @pReceiptsWithFactoryNameCode.nodes('/POLines/POLine') AS line(item) 

      SELECT  
         @MAXTRANSID = COALESCE(MAX(trans_id),0)
      FROM 
         PartsTrack_Receipt_Trans (NOLOCK) 
      WHERE 
         trans_id IS NOT NULL

      UPDATE rt 
      SET trans_id = @MAXTRANSID + temp.id,
          factory_name_code = temp.factory_name_code
      FROM PartsTrack_Receipt_Trans_BKP rt 
      INNER JOIN #tmpReceiptsWithFactoryNameCode temp ON rt.receipt_ack_nbr = temp.ran 
                                                      AND rt.po_nbr = temp.po_nbr 
                                                      AND rt.po_line_nbr = temp.po_line_nbr
END

public static int ExecuteNonQuery(string pConnectionString, CommandType pCommandType, string pCommandText, SqlParameter[] pSqlParameters)

        SqlConnection lSqlConnection = null;

        try
        
            lSqlConnection = new SqlConnection(pConnectionString);

            SqlCommand lSqlCommand = new SqlCommand();
            lSqlCommand.CommandType = pCommandType;
            lSqlCommand.Connection = lSqlConnection;
            lSqlCommand.CommandText = pCommandText;
            lSqlCommand.CommandTimeout = 180;

            if (pSqlParameters != null)
            
                foreach (SqlParameter lSqlParameter in pSqlParameters)
                    lSqlCommand.Parameters.Add(lSqlParameter);
            

            lSqlConnection.Open();

            return lSqlCommand.ExecuteNonQuery();
        
        catch (SqlException sqlExp)
        
            throw sqlExp;
        
        catch (Exception exp)
        
            throw exp;
        
        finally
        
            if (lSqlConnection != null && lSqlConnection.State != ConnectionState.Closed)
                lSqlConnection.Close();
        
    

我搜索了一下,发现这是正确的传递xml参数的方式。

那我做错了什么?

谢谢

已编辑:

我发现了问题。所有建议的方法都是正确的,但由于 xml 区分大小写,我发现我传递的 xml 节点不匹配。

【问题讨论】:

调试时会发生什么?有什么例外吗? 没有例外,它通过返回值为-1的ExecuteNonQuery。我想知道这是否是将 xml 传递给存储过程的方式。 实际通过 C# 代码传递的 XML 字符串的值是多少?如果您直接将其传递给 SP 会有问题吗? 嗯,您能否也编辑您的问题以添加SqlHelper.ExecuteNonQuery 的定义? 您是否尝试过将 sql 参数类型更改为 SqlDbType.varchar 而不是 SqlDbType.Xml?我想也许 SqlDbType.Xml 期望 xml 以其他方式而不是字符串传递。 【参考方案1】:

尝试传递 XML 值 with SqlXml。那么它应该可以工作了。

【讨论】:

也试过这样 - SqlParams[0].Value = new SqlXml(new XmlTextReader(xmlDocument.InnerXml, XmlNodeType.Document, null));但不工作【参考方案2】:

您需要将变量xml 作为SqlXml 类的实例传入。你可以这样做:

SqlParams[0].Value = new SqlXml(new MemoryStream(Encoding.UTF8.GetBytes(xml)));

【讨论】:

我认为我将数据作为 xml 属性而不是元素传递。这可能是一个原因吗? 但是你说你得到的字符串当你直接传递它时有效吗?

以上是关于将 xml 作为参数传递给 SQL Server 中的存储过程的主要内容,如果未能解决你的问题,请参考以下文章

如何将 XML 数据作为参数传递给从 C# 到 Sql 服务器的 TVP 参数

将 Access 表日期值作为参数传递给 SQL Server 存储过程

在 ASP.Net Core 项目中使用 ADO.Net 将 JSON 类型作为参数传递给 SQL Server 2016 存储过程

将xml作为输入参数传递给存储过程

将列作为参数传递给 SQL Server 中的 dateadd

将参数传递给 SQL Server 中的视图