存储过程不返回任何列,仅返回整数

时间:2017-01-29 11:52:07

标签: sql-server asp.net-mvc tsql c#-4.0 entity-framework-6

我在导入存储过程时遇到了权限框架6.0.0.0的问题,无论我做什么都不返回结果集,而是只返回整数或设置为none。 下面是sp。

alter proc spGetProd
@Prod nvarchar(500)
as
begin
SET FMTONLY OFF
IF OBJECT_ID('tempdb..##PRODUCTTABLE') IS NOT NULL DROP TABLE ##PRODUCTTABLE
DECLARE @MYQUERY nvarchar(MAX), @my_Div nvarchar(500);
set @my_Div = REPLACE(@Prod, ',', ''',''');

SET @MYQUERY = 'SELECT DISTINCT [GNo],[GName]    
into ##PRODUCTTABLE FROM ABC
where Div IN ('''+@my_Div+''') 
order by GNo'

EXEC (@MYQUERY)
SELECT GNo, GName FROM ##PRODUCTTABLE;
drop table  ##PRODUCTTABLE;
end

无论我做什么,无论我设置SET FMTONLY OFF / ON,都行不通。我做了很久以后它只工作了一次,当我设置SET FMTONLY OFF然后删除它并且它适用于那个sp但是对于其他存储过程它不起作用。即使我从select * from ##PRODUCTTABLE;获取结果集或指定上面的列。 这是我在MVC中的行动。

public JsonResult GetData()
        {
         var allProducts = gentity.spGetProd("AB"); //return type shows as int.
         return Json(allProducts, JsonRequestBehavior.AllowGet);
       }

是否还有其他解决方法,因为我的应用程序主要依赖于存储过程,这些存储过程通常会从上面的临时表中返回数据。

3 个答案:

答案 0 :(得分:1)

EF无法从存储过程派生结果集的结构,因为它是动态组合的。但是你可以解决这个问题,同时简化存储过程。

首先,创建一个Split函数,例如this one。然后在存储过程中使用它:

...
BEGIN
    SELECT DISTINCT [GNo],[GName]    
    FROM ABC
    JOIN dbo.Split(@Prod) AS prod ON prod.Name = ABC.Div 
    order by GNo
END

现在EF可以从SELECT语句中推断出返回的列。

答案 1 :(得分:1)

问题出在您的存储过程中。你的问题很简单,而且你把这些东西弄得很复杂。

只需在数据库中创建此功能。

CREATE FUNCTION dbo.SplitStrings
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(@List, @Delimiter, '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );
GO

现在您的存储过程看起来像

ALTER PROC spGetProd
    @Prod nvarchar(500)
AS
BEGIN
 SET NOCOUNT ON;
 SELECT DISTINCT [GNo],[GName]    
 FROM ABC
 WHERE Div IN (SELECT Item FROM dbo.SplitStrings(@Prod,','))
 ORDER BY GNo;
END

没有临时表,没有额外的变量,没有EXEC,没有对象掉线。只是一个明确的EF选择声明。

答案 2 :(得分:0)

目前尚不清楚如何实际执行程序(动态或使用某种映射)。如果我没记错的话,我在SQL Server 2012中遇到了与结果集结构(模式)相关的一些问题,我不得不使用WITH RESULT SETS来明确告诉预期的结果集结构。

在实体框架中,这可以通过以下方式实现:

var query = "EXECUTE spGetProd @Prod WITH RESULT SETS ((GNo INT, GName NVARCHAR(1024)))";
var result = context.Database.SqlQuery<EntityType>(sql).ToList();

反馈后修改

如果结果集结构是动态的,我不认为实体框架在这里是合适的。相反,请获取results into a DataSet

如果已知最大结构,则可以将DataSet信息传输到对象列表中:

public static DataTable ConvertTo<T>(IList<T> list)
{
    DataTable table = CreateTable<T>();
    Type entityType = typeof(T);
    PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType);

    foreach (T item in list)
    {
        DataRow row = table.NewRow();

        foreach (PropertyDescriptor prop in properties)
        {
            row[prop.Name] = prop.GetValue(item);
        }

        table.Rows.Add(row);
    }

    return table;
}