存储过程返回int而不是结果集

我有一个包含动态选择的存储过程。 像这样的东西:

ALTER PROCEDURE [dbo].[usp_GetTestRecords] --@p1 int = 0, --@p2 int = 0 @groupId nvarchar(10) = 0 AS BEGIN SET NOCOUNT ON; DECLARE @query NVARCHAR(max) SET @query = 'SELECT * FROM CUSTOMERS WHERE Id = ' + @groupId /* This actually contains a dynamic pivot select statement */ EXECUTE(@query); END 

在SSMS中,存储过程运行正常并显示结果集。

在使用Entity Framework的C#中,它显示返回一个int而不是IEnumerable

 private void LoadTestRecords() { TestRecordsDBEntities dataContext = new TestRecordsDBEntities(); string id = ddlGroupId.SelectedValue; List list = dataContext.usp_GetTestRecords(id); //This part doesn't work returns int GridView1.DataSource = list; } 

usp_GetTestRecords生成的函数

 public virtual int usp_GetTestRecords(string groupId) { var groupIdParameter = groupId != null ? new ObjectParameter("groupId", groupId) : new ObjectParameter("groupId", typeof(string)); return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("usp_GetTestRecords", groupIdParameter); } 

entity framework无法分辨您的存储过程返回的内容。 我成功创建了一个表变量,它反映了SELECT语句中的数据。 只需插入表变量,然后从该表变量中选择。 EF应该拿起它。

当我有一个包含“exec”调用的存储过程到临时表时,我得到了这个,例如:

 insert into #codes (Code, ActionCodes, Description) exec TreatmentCodes_sps 0 

似乎entity framework对程序应返回的内容感到困惑。 我遇到的解决方案是将其添加到sproc的顶部:

 SET FMTONLY OFF 

在此之后,一切都很好。

我遇到了同样的问题, 在这里找到了解决方案

  1. 转到你的.edmx
  2. 在模型浏览器窗口/函数导入中找到您的过程,然后双击它
  3. 将返回类型更改为您想要的
  4. 保存.edmx并再次检查返回类型。

截图

它应该是你现在需要的。

请参阅Ladislav Mrnka在此Stack Overflowpost中的答案https://stackoverflow.com/a/7131344/4318324

我有同样的基本问题。

添加

 SET FMTONLY OFF 

在导入期间尝试导入的过程将解决此问题。 除非数据库的目的仅仅是为EF(entity framework)提供模式,否则最好在之后删除该行。

谨慎的主要原因是EF在尝试获取元数据时使用此设置来防止数据突变。

如果从数据库刷新实体模型,则在其中包含此行的任何过程都可能仅通过尝试获取模式来更新该数据库中的数据。

我想在此添加一个注释,因此不需要完全扫描其他链接。

如果你想尝试使用FMTONLY,请记住几件事。

当FMTONLY打开时:
   1)仅返回模式(否)行。
     类似于在where子句中添加一条毯子假语句(即“where 1 = 0”)
   2)忽略流控制语句

设置fmtonly

如果1 = 1
开始
    选择1 a
结束
其他
开始
    选择1 a,2 b
结束

而1 = 1
选择1 c

以上内容不返回任何行和三个查询中的每一个的元数据

出于这个原因,有些人建议以一种利用它不遵守流量控制的方式将其切换掉

如果1 = 0
开始
    设置fmtonly off
结束

事实上,您可以使用它来引入跟踪它的逻辑

设置fmtonly off
声明@g varchar(30)
设置@g ='fmtonly设置为关闭'

如果1 = 0
开始
    设置fmtonly off
    设置@g ='fmtonly设置为' 
结束

选择@g

在尝试使用此function之前要非常仔细地考虑因为它已被弃用并且可能使sql非常难以遵循

需要理解的主要概念如下

 1. EF打开FMTONLY以防止MUTATING数据执行存储过程
   何时在模型更新期间执行它们。
    (从中得出)

 2.在EF将尝试执行模式扫描的任何过程中关闭FMTONLY
    (可能是ANY和EACHONE)引入了变异数据库的潜力
   每当*任何人*尝试更新其数据库模型时的数据。

如果存储过程在结果集中没有主键,Entity Framework将自动返回标量值。 因此,您必须在select语句中包含主键列,或者使用主键创建临时表,以便Entity Framework返回存储过程的结果集。

为存储过程生成模型类时,错误地选择了标量返回结果。 您应该从实体模型中删除存储过程,然后重新添加存储过程。 在存储过程的对话框中,您可以选择所需的返回类型。 不要只编辑生成的代码..这可能现在可以使用,但如果您对模型进行其他更改,则可以替换生成的代码。

我有同样的问题,我用’AS’关键字更改了返回字段的名称并解决了我的问题。 此问题的一个原因是使用SQL Server保留关键字命名列名称。

例子是休耕:

 ALTER PROCEDURE [dbo].[usp_GetProducts] AS BEGIN SET NOCOUNT ON; SELECT , p.Id , p.Title , p.Description AS 'Description' FROM dbo.Products AS p END 

我考虑过这一点,我想我有一个更好/更简单的答案

如果你有一个复杂的存储,给entity framework一些困难(对于使用FMTONLY标签来获取模式的当前版本的Entity Framework)

考虑在存储过程开始时进行下面的操作。

 -  [columnlist]匹配您希望EF为您的存储过程选取的架构

如果1 = 0
开始
    选择 
        [columnlist]
    来自[表格列表和连接]
    其中1 = 0
结束

如果您可以将结果集加载到表变量中,则可以执行以下操作以帮助保持模式同步

将@tablevar声明为表
 (
     blah int
     ,moreblah varchar(20)
 )

如果1 = 0
开始
    从@tablevar中选择*
结束

 ...
 - 将数据加载到@tablevar
从@tablevar中选择*

只需改为

 ALTER PROCEDURE [dbo].[usp_GetTestRecords] --@p1 int = 0, --@p2 int = 0 @groupId nvarchar(10) = 0 AS BEGIN SET NOCOUNT ON; SELECT * FROM CUSTOMERS WHERE Id = @groupId END 

我知道这是一个老线程,但万一有人遇到同样的问题,我会告诉我的困境。

作为查找问题的帮助,在添加存储过程时运行sql profiler。 然后,您可以查看作为参数传递的entity framework以生成结果集。 我想几乎总是会传递空参数值。 如果你通过连接字符串值和参数值来动态生成sql,而有些则为null,那么sql将会中断并且你不会得到一个返回集。

我不需要生成临时表或任何只是exec命令。

希望能帮助到你

如果你需要这样做,那么你可能最好只做一部分dbcontext并自己创建C#函数,它将使用SqlQuery返回你需要的数据。 与其他一些选项相比的优势是:

  1. 模型更新时不必更改任何内容
  2. 如果你直接在生成的类中进行覆盖,不会被覆盖(有人提到这个就好像它是一个选项:))
  3. 不必向proc本身添加任何可能现在或稍后产生副作用的东西

示例代码:

  public partial class myEntities { public List usp_GetTestRecords(int _p1, int _p2, string _groupId) { // fill out params SqlParameter p1 = new SqlParameter("@p1", _p1); ... obj[] parameters = new object[] { p1, p2, groupId }; // call the proc return this.Database.SqlQuery(@"EXECUTE usp_GetTestRecords @p1, @p2, @groupId", parameters).ToList(); } } 

导入期间

SET FMTONLY ON可用于获取sp模式。

如果更改sp并想要更新新的,则应从edmx文件(从xml)删除旧的已定义函数,因为虽然从模型浏览器中删除sp,但在edmx中不会删除它。 例如;

     

我有同样的问题,当我完全删除相应sp的FuctionImport标签时,模型更新正确。 您可以通过从visual studio中搜索函数名称来查找标记。

您可以运气打开模型浏览器,然后转到function导入,双击有问题的存储过程,然后手动单击“获取列信息”,然后单击“创建新的复杂类型”。 这通常可以解决问题。

我也有这个问题,但经过数小时的在线搜索,上述方法都没有帮助。 最后我知道如果你的存储过程将一些参数作为null并且在查询执行中产生任何错误,那么会发生这种情况。 entity framework将通过定义复杂的实体模型来生成存储过程的方法。 由于该值为null,因此存储过程将返回int值。

请检查您的商店程序,提供空值为空的结果集。 它会解决你的问题。 希望。