Как вернуть XML из хранимой процедуры?

Я создал хранимую процедуру, которая возвращает XML, и я также хотел бы вернуть этот XML в методе, который я создал.

У меня две проблемы. Во-первых, после некоторого поиска не рекомендуется использовать .ExecuteScalar();, потому что он обрезает строки более 2033 символов.

Итак, я нашел функцию под названием ExecuteXMlReader(), но в Visual Web Developer 2010 Express, которая работает на .NET 4.0 (С#), она выдает ошибку "System.Data.SqlClient.SqlCommand' does not contain a definition for 'ExecuteXMlReader' and no extension method 'ExecuteXMlReader' accepting a first argument of type 'System.Data.SqlClient.SqlCommand' could be found"

Вот моя хранимая процедура:

CREATE PROCEDURE dbo.GETReport
    (@ReportDate date)
AS
SELECT * FROM ReportTbl
WHERE ReportDate = @ReportDate
for xml auto, elements

set nocount on;

RETURN

Вот мой метод:

using System.Data;
using System.Data.SqlClient;

...

        //connect        
        SqlConnection conn = new SqlConnection("Data Source=localhost; User Id=foo; Password=foo; Initial Catalog=Database1");
        conn.Open();

        //create command
        SqlCommand cmd = new SqlCommand("dbo.GETReport", conn);
        cmd.Parameters.AddWithValue("@ReportDate", "3/24/2011"); 
        cmd.CommandType = CommandType.StoredProcedure;

        DataReader rd = cmd.ExecuteXMlReader(); //this is where error is occuring
        //also, it is throwing an error for DataReader as well saying there is no
        //type of namespace with that name
        rd.Read();

        string s = rd.ReadOuterXml(); //also dont know if this is how i should return the XML

Во-вторых, в дополнение к проблеме ExecuteXMlReader(), я не знаю, вернет ли строка правильный способ возврата XML в первую очередь... Есть ли другой тип объекта, который я должен преобразовать? Или другую функцию, которую я должен использовать?

Спасибо заранее!

Ответы

Ответ 1

Во-первых, SqlCommand имеет метод ExecuteXmlReader, а не ExecuteXmlReader, как вы написали (это ошибка). Во-вторых, метод SqlCommand.ExecuteXmlReader возвращает значение типа XmlReader, а не DataReader, как в вашем примере. Поэтому, изменив свой код на:

using (XmlReader reader = cmd.ExecuteXmlReader())
{
    while(reader.Read())
    {
        string s = reader.ReadOuterXml();
        // do something with s
    }
}

должен решить проблему.

Ответ 2

У меня были проблемы с простым подходом от @Alex и удача с этим подходом:

// Execute a SqlCommand that you've created earlier.
// (Don't forget your 'using' statements around SqlConnection, SqlCommand and XmlReader!)
// This is where our XML will end up 
var xmlDocument = new XmlDocument();

using (XmlReader xmlReader = cmd.ExecuteXmlReader())
{
    // Now xmlReader has the XML but no root element so we can't
    // load it straight into XmlDocument :( But we can use XPathDocument
    // to add a node for us first.
    var xp = new XPathDocument(xmlReader);
    var xn = xp.CreateNavigator();
    XmlNode root = xmlDocument.CreateElement("YourFavouriteRootElementName");
    root.InnerXml = xn.OuterXml;
    xmlDocument.AppendChild(root);
}

// Now xmlDocument has all the XML you have dreamed of

Использование reader.Read()... var s = reader.ReadOuterXml() каким-то образом пропустило некоторые элементы в моем более сложном XML. Я не удосужился разобраться, почему, но переключение на XPathDocument мне XPathDocument.