Linq存储过程返回XML

我正在使用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 

LINQentity framework:

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

这里ProductList列表返回-1。

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

注意:我也尝试了类似的方法: ExecuteSqlCommand,SqlQuery没有帮助。

基于MSDN :

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

因此, ExecuteSqlCommandInsertUpdateDelete等查询返回一个int,它表示单个非查询影响数。 所以ExecuteSqlCommand不适合查询。

这也是一个常见问题,因为entity framework不能支持开箱即用的存储过程返回值 ,这是因为EF是ORM,而不是SQL替换。 在Model First中检查以下链接是否存在类似问题:

使用Entity Framework从存储过程中获取数据

这与ExecuteNonQuery

尽管使用了查询字符串,但在使用sql COUNT时,ExecuteNonQuery返回-1

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

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

我想你可以像这样使用SQLQuery

 using (var dbcontext = new DBContext()) { //Reading stored procedure results as List var r = dbcontext.Database.SqlQuery("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($"{xmlString}"); } 

注意:要从存储过程中获取记录,您需要添加SET NOCOUNT ON;BEGIN之后;)。

 CREATE PROCEDURE [dbo].[xml_test] AS BEGIN SET NOCOUNT ON; SELECT * from dbo.AspNetUsers FOR XML RAW; END 

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

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