Хранимая процедура Linq для возврата XML

Я использую подход Entity Framework code-first. Я хочу вызвать хранимую процедуру из DbContext class и получить вывод XML.

хранимая процедура (SQL Server):

CREATE PROCEDURE xml_test    
AS
BEGIN
    DECLARE @xml1 xml

    SET @xml1 = (SELECT * from Product FOR XML RAW) 

    SELECT @xml1 AS my_xml
END

Linq Entity Framework:

using (DBContext db = new DBContext())
{
    var ProductList = await db.Database.ExecuteSqlCommandAsync("exec xml_test");
}
на ProductList list возвращает -1.

Я хочу получить вывод xml, который возвращается хранимой процедурой.

Примечание: я также пробовал такие методы, как: ExecuteSqlCommand, SqlQuery без посторонней помощи.

4 ответов


на основе MSDN:

для инструкций UPDATE, INSERT и DELETE возвращаемое значение-это количество строк, затронутых командой. Если триггер существует в вставляемой или обновляемой таблице, возвращаемое значение включает число строк, затронутых операцией вставки или обновления, и число строк, затронутых триггером или триггерами. Для всех других типов операторов возвращаемое значение равно -1. Если происходит откат, возвращаемое значение также -1.

так ExecuteSqlCommand возвращает int для таких запросов, как Insert,Update,Delete и это означает, что число изменяемой строки без запроса. Так что ExecuteSqlCommand не подходит для запроса.

и это общая проблема, потому что Entity Framework не может поддерживать возвращаемые значения хранимых процедур из коробки и это потому, что EF является ORM, а не заменой SQL. Проверьте следующую ссылку для аналогичной проблемы в Модель:

получение данных из хранимой процедуры с Entity Framework

и ExecuteNonQuery:

ExecuteNonQuery возвращает -1 при использовании SQL COUNT, несмотря на строку запроса

решение: для запросов необходимо использовать Database.SqlQuery<TElement> способ:

var ProductList = db.Database.SqlQuery<string>("exec xml_test").ToList();

Я думаю, вы можете использовать SQLQuery такой:

using (var dbcontext = new DBContext())
{
    //Reading stored procedure results as List<string>
    var r = dbcontext.Database.SqlQuery<string>("EXEC xml_test").ToList(); //Note: EXEC is optional

    //Joining strings to one string that causes in resulting long strings
    var xmlString = string.Join("", r);

    //Now you can load your string to a XmlDocument
    var xml = new XmlDocument();

    //Note: You need to add a root element to your result
    xml.LoadXml($"<root>{xmlString}</root>");
}

Примечание: Для получения записей из хранимой процедуры вы должны добавить SET NOCOUNT ON; после BEGIN ;).

CREATE PROCEDURE [dbo].[xml_test] 
AS
BEGIN
    SET NOCOUNT ON;

    SELECT * from dbo.AspNetUsers FOR XML RAW;
END

Как упоминалось shA.t"ДЛЯ XML " можно использовать. Однако одна вещь, о которой нужно позаботиться при использовании, - это усечение строки / XML (возвращаемое после вызова функции через EF) примерно на 2k символов, чтобы обработать этот сценарий, вы можете посмотреть на этой. Также, если позволяет дизайн кода, Вы даже можете использовать Ouptput параметры с Enitity Framework.


Database.ExecuteSqlCommand выполняет команды, используемые для работы CRUD, а не запросы.

используя Database.SqlQuery для запросов. Он будет возвращать элементы данного типа, но xml не является примитивным типом и, вероятно, это причина, по которой LINQ не работает. Попробуй!--4--> XML в хранимой процедуре nvarchar(max) это будет типа String.

. Так что ваша хранимая процедура должна выглядеть так:

    CREATE PROCEDURE xml_test    
AS
BEGIN
    DECLARE @xml1 xml

    SET @xml1 = (SELECT * from Product FOR XML RAW) 

    SELECT CAST(@xml1 as nvarchar(max))
END