I am using Entity Framework code-first approach. I want to call a stored procedure from the DbContext
class and to get XML output.
Stored procedure (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");
}
Here the ProductList
list is returning -1.
I want to get the xml output which is returned by the stored procedure.
Note: I have also tried methods like: ExecuteSqlCommand, SqlQuery with no help.
Based on MSDN :
For UPDATE, INSERT, and DELETE statements, the return value is the number of rows affected by the command. When a trigger exists on a table being inserted or updated, the return value includes the number of rows affected by both the insert or update operation and the number of rows affected by the trigger or triggers. For all other types of statements, the return value is -1. If a rollback occurs, the return value is also -1.
So ExecuteSqlCommand
returns an int for queries like Insert
, Update
, Delete
and it means the number of row affected by a single non-query. So ExecuteSqlCommand
is not suitable for querying.
Also this is a common problem because Entity Framework cannot support Stored Procedure Return values out of the box and it is because EF is an ORM, not a SQL replacement. Check the following link for similar problem in Model First :
Getting data from stored procedure with Entity Framework
And this with ExecuteNonQuery
:
ExecuteNonQuery returning -1 when using sql COUNT despite the query string
The solution : for queries you need to use Database.SqlQuery<TElement>
method:
var ProductList = db.Database.SqlQuery<string>("exec xml_test").ToList();
I think you can use SQLQuery
like this:
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>");
}
Note: To get records from your stored procedure you need to add
SET NOCOUNT ON;
afterBEGIN
;).
CREATE PROCEDURE [dbo].[xml_test]
AS
BEGIN
SET NOCOUNT ON;
SELECT * from dbo.AspNetUsers FOR XML RAW;
END
Database.ExecuteSqlCommand
executes commands used for CRUD operation, not querying.
Using Database.SqlQuery
is for queries. It will return elements of a given type but xml
isn't a primitive type and probably it's a reason why LINQ not working. Try cast
xml in stored procedure to nvarchar(max)
this will be string type.
. So your stored procedure should look like:
CREATE PROCEDURE xml_test
AS
BEGIN
DECLARE @xml1 xml
SET @xml1 = (SELECT * from Product FOR XML RAW)
SELECT CAST(@xml1 as nvarchar(max))
END
As mentioned by shA.t " FOR XML " can be used. However one thing to take care of while using is the truncation of string/XML (returned after function call via EF) at around 2k characters, to handle this scenario you can have a look at this . Also if the code design allows, you can even use Ouptput parameters with Enitity Framework .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.