存储过程和XML

时间:2009-07-06 17:25:21

标签: c# asp.net sql-server xml stored-procedures

我收到此错误:

The error description is 'Only one top level element is allowed in an XML document.'.
Could not find prepared statement with handle 0.
The XML parse error 0xc00ce555 occurred on line number 1, near the XML text "<value1>34</value1><value1>33</value1><value1>32</value1>".
The statement has been terminated. 

这是存储过程调用:

 public bool HideFromList(string commentList, bool state)
{
//commentList =<values><value1>34</value1><value1>33</value1><value1>32/value1></values>
  using (SqlConnection cn = new SqlConnection(this.ConnectionString))
 {
       SqlCommand cmd = new SqlCommand("VisibleFromList", cn);
       cmd.CommandType = CommandType.StoredProcedure;
       cmd.Parameters.Add("@XMLDoc", SqlDbType.Xml).Value = commentList;
       cmd.Parameters.Add("@state", SqlDbType.Int).Value = state;
       cn.Open();
       int ret =  cmd.ExecuteNonQuery();

       return (ret == 1);
 }          

}

这是我的存储过程:

ALTER PROCEDURE dbo.VisibleFromList
(
    @XMLDoc   xml,
    @state     BIT
)

AS
BEGIN


DECLARE @docHandle int
EXEC sp_xml_preparedocument @docHandle OUTPUT, @XMLDoc 


UPDATE tbh_Comments
SET Visible = @state WHERE 
CommentID IN (SELECT * FROM OPENXML(@docHandle, '/values/value1', 2) WITH (value1 INT '.'))


END

但如果我使用嵌入式输入字符串修改SP,它确实有效:

ALTER PROCEDURE dbo.VisibleFromList
(
    @XMLDoc   xml,
    @state     BIT
)

AS
BEGIN


DECLARE @docHandle int
EXEC sp_xml_preparedocument @docHandle OUTPUT, 
'<values>
 <value1>33</value1>
<value1>34</value1>  
</values>'

UPDATE tbh_Comments
SET Visible = @state WHERE 
CommentID IN (SELECT * FROM OPENXML(@docHandle, '/values/value1', 2) WITH (value1 INT '.'))


END

如何使用输入参数?

4 个答案:

答案 0 :(得分:3)

你是否肯定你的评论列表如你所描述的那样?

//commentList =<values><value1>34</value1><value1>33</value1><value1>32/value1></values>

如果您的列表确实与此类似,那么它应该有效。

根据您的错误,似乎<values>元素可能不存在:

near the XML text "<value1>34</value1><value1>33</value1><value1>32</value1>".

答案 1 :(得分:3)

我建议您将程序转换为使用XML Data Type Methods。与sp_prepare_document不同,这些内容由SQL引擎本机实现,它们可以更好地与查询交互,生成更好的错误消息,并don't run the risk of leaking document handles

因此,在您的程序中,您可以执行以下操作:

declare @XMLDoc xml;
select @XMLDoc =N'<values>
 <value1>33</value1>
<value1>34</value1>  
</values>';


UPDATE tbh_Comments
SET Visible = @state WHERE 
CommentID IN (
    SELECT v.value('.', 'INT') as CommentID
    FROM @XMLDoc.nodes('/values/value1') t(v))

答案 2 :(得分:1)

如果你正在进行某种循环,我发现这样做很有帮助:

XElement entityListElement = new XElement("values");
XElement entityElement = new XElement(
                    "value",
                    new XElement("value1", "15"));
entityListElement.Add(entityElement);

然后传入entityListElement.ToString()。

这也使得(可以说)更容易进行更改并让.NET为您执行XML生成。

答案 3 :(得分:0)

试试这个

ALTER PROCEDURE dbo.VisibleFromList (
    @XMLDoc   xml,
    @state     BIT )

AS BEGIN


DECLARE @docHandle int EXEC sp_xml_preparedocument @docHandle OUTPUT, @XMLDoc 


 UPDATE tbh_Comments SET Visible = @state WHERE  CommentID IN (SELECT * 
 FROM OPENXML(@docHandle, '/root/values/value1', 2) WITH (value1 INT '.'))


END