Linq存储过程返回XML

时间:2016-12-22 06:34:26

标签: c# xml entity-framework linq stored-procedures

我正在使用Entity Framework代码优先方法。我想从DbContext类调用存储过程并获取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实体框架:

using (DBContext db = new DBContext())
{
    var ProductList = await db.Database.ExecuteSqlCommandAsync("exec xml_test");
}

此处ProductList列表返回-1。

我想获取存储过程返回的xml输出。

注意:我也尝试过这样的方法: ExecuteSqlCommand,SqlQuery ,没有任何帮助。

4 个答案:

答案 0 :(得分:6)

基于MSDN

  

对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。当插入或更新的表上存在触发器时,返回值包括插入或更新操作影响的行数以及受触发器或触发器影响的行数。对于所有其他类型的语句,返回值为-1。如果发生回滚,则返回值也为-1。

因此,ExecuteSqlCommand会为InsertUpdateDelete之类的查询返回一个int,这意味着单个行影响的数量非查询。所以ExecuteSqlCommand不适合查询。

这也是一个常见问题,因为实体框架不能支持开箱即用的存储过程返回值,这是因为EF是ORM,而不是SQL替代品。请检查以下链接,了解模型优先

中的类似问题

Getting data from stored procedure with Entity Framework

这与ExecuteNonQuery

ExecuteNonQuery returning -1 when using sql COUNT despite the query string

解决方案: 对于查询,您需要使用Database.SqlQuery<TElement>方法:

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

答案 1 :(得分:4)

我认为你可以像这样使用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

答案 2 :(得分:2)

Database.ExecuteSqlCommand执行用于CRUD操作的命令,而不是查询。

使用Database.SqlQuery用于查询。它将返回给定类型的元素,但xml不是原始类型,这可能是LINQ无法工作的原因。在存储过程中尝试cast xml到nvarchar(max)这将是字符串类型。

。因此,您的存储过程应如下所示:

    CREATE PROCEDURE xml_test    
AS
BEGIN
    DECLARE @xml1 xml

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

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

答案 3 :(得分:2)

正如shA.t&#34; FOR XML&#34;可以使用。但是,使用时要注意的一件事是截断字符串/ XML(通过EF调用函数后返回)大约2k个字符,为了处理这种情况,你可以查看this。此外,如果代码设计允许,您甚至可以使用Ouptput parameters with Enitity Framework