5

注:検索でこの正確な質問を見つけることができませんでした。ここでスタックオーバーフローで似たような質問を見つけたので、解決策にたどり着きました。問題を抱えている次の人がより簡単に解決策を見つけられるように、質問と解決策を投稿しています。それがまだ可能であれば、私はCommunityWikiに質問したでしょう-私はこれからの担当者を探していません.


XmlADO.NET を使用して、次の型のパラメーターを受け入れる 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 to 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をストアド プロシージャに渡す正しい方法は何ですか?

4

2 に答える 2

11

SqlClient コードでは、XElement を直接渡すことはできません。

できることの 1 つは、System.Data.SqlTypes.SqlXmlクラスを使用して XML を渡すことです。

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

XmlReaderコードによっては、コードから返さCreateReaderれた をusingブロックに配置する必要がある場合があります。

于 2011-12-16T02:12:32.310 に答える
0

John Saunders の回答に基づいて構築した 2 つの拡張メソッドを次に示します。

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())
        });
    }
}
于 2015-02-12T15:12:08.303 に答える