2011-12-16 56 views
5

注意:我无法在搜索中找到这个确切的问题。我在Stack Overflow上发现了一个类似的问题,这导致我找到了解决方案。我发布了问题和解决方案,以便下一个遇到问题的人可以更轻松地找到解决方案。如果还有可能的话,我会提出CommunityWiki这个问题 - 我不想从这里寻找代表。System.InvalidCastException:无法将参数值从XElement转换为字符串


我想使用ADO.NET调用其接受Xml类型的参数SQL Server 2005的存储过程:

CREATE PROCEDURE dbo.SomeProcedure(
    @ListOfIds Xml) 
AS 
BEGIN 
    DECLARE 
      @Ids TABLE(ID Int); 
    INSERT INTO @Ids 
    SELECT ParamValues.ID.value('.', 'Int') 
    FROM @ListOfIds.nodes('/Persons/id') AS ParamValues(ID); 

    SELECT p.Id, 
      p.FirstName, 
      p.LastName 
    FROM Persons AS p 
     INNER JOIN @Ids AS i ON p.Id = i.ID; 
END; 

我通过XML作为LINQ到XML的XElement对象

var idList = new XElement(
    "Persons", 
    from i in selectedPeople 
    select new XElement("id", i)); 

SqlCommand cmd = new SqlCommand 
       { 
        Connection = conn, 
        CommandText = "dbo.SomeProcedure", 
        CommandType = CommandType.StoredProcedure 
       }; 
cmd.Parameters.Add(
    new SqlParameter 
    { 
     ParameterName = "@ListOfIds", 
     SqlDbType = SqlDbType.Xml, 
     Value = idList) 
    }); 
using (var reader = cmd.ExecuteReader()) 
{ 
    // process each row 
} 

这种失败与异常的ExecuteReader行:

System.InvalidCastException:无法将参数值从一个的XElement转换为字符串。 ---> System.InvalidCastException:对象必须实现IConvertible

什么是将XElement传递给存储过程的正确方法?

+1

的可能重复[C#/ SQL - 什么手续错SqlDbType.Xml(http://stackoverflow.com/questions/574928/c-sql-whats-wrong-with-sqldbtype-xml -in-procedures) – 2011-12-16 02:11:04

回答

9

SqlClient代码不允许直接传递XElement。

有一两件事你可以做的是使用System.Data.SqlTypes.SqlXml class传递XML:

cmd.Parameters.Add(
    new SqlParameter 
    { 
     ParameterName = "@ListOfIds", 
     SqlDbType = SqlDbType.Xml, 
     Value = new SqlXml(idList.CreateReader()) 
    }); 

根据您的代码,您可能需要把XmlReaderCreateReader码返回到一个using块。

0

下面是我根据约翰桑德斯的回答建立的两种扩展方法。

public static class ExtensionMethods 
{ 
    public static void AddXml(this SqlParameterCollection theParameters, string name, XElement value) 
    { 
     theParameters.Add(new SqlParameter() 
     { 
      ParameterName = name, 
      SqlDbType = SqlDbType.Xml, 
      Value = new SqlXml(value.CreateReader()) 
     }); 
    } 

    public static void AddXml(this SqlParameterCollection theParameters, string name, string value) 
    { 
     theParameters.Add(new SqlParameter() 
     { 
      ParameterName = name, 
      SqlDbType = SqlDbType.Xml, 
      Value = new SqlXml(XElement.Parse(value).CreateReader()) 
     }); 
    } 
} 
相关问题