2011-12-16 40 views
5

Nota: No he podido encontrar esta pregunta exacta en una búsqueda. Encontré una pregunta algo similar aquí en Stack Overflow, que me llevó a la solución. Estoy publicando la pregunta y la solución para que la siguiente persona con el problema pueda encontrar la solución más fácilmente. Habría hecho la pregunta CommunityWiki si eso todavía fuera posible - No estoy buscando representante de esto.System.InvalidCastException: no se pudo convertir el valor del parámetro de un XElement a una cadena


Estoy intentando utilizar ADO.NET para llamar a un procedimiento almacenado de SQL Servidor 2005, que acepta un parámetro del tipo Xml:

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; 

paso el XML como LINQ al objeto XML XElement

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

tarde

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 
} 

Esta falla en la línea ExecuteReader con la excepción:

System.InvalidCastException: Error al convertir el valor de parámetro de un XElement en una cadena. ---> System.InvalidCastException: El objeto debe implementar IConvertible

¿Cuál es la forma correcta de pasar una XElement a un procedimiento almacenado?

+1

posible duplicado de [C#/SQL - ¿Qué hay de malo en SqlDbType.Xml en los procedimientos] (http://stackoverflow.com/questions/574928/c-sql-whats-wrong-with-sqldbtype-xml -in-procedures) –

+0

No es un duplicado, es una excepción diferente. –

+1

¿Qué problema tienes? ¿Probaste algo y no funcionó? – JsonStatham

Respuesta

9

El código SqlClient no permite que un XElement pase directamente.

Una cosa que puede hacer es utilizar el System.Data.SqlTypes.SqlXml class para pasar el XML:

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

Dependiendo de su código, puede que tenga que colocar el XmlReader volvió del código CreateReader en un bloque using.

0

Aquí hay dos métodos de extensión que construí en base a la respuesta de John Saunders.

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()) 
     }); 
    } 
} 
Cuestiones relacionadas