Хранимая процедура 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