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

Rod*_*Rod 29 c# sql entity-framework

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

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
Run Code Online (Sandbox Code Playgroud)

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

在使用实体框架的C#中,它显示返回int而不是IEnumerable

private void LoadTestRecords()
{
    TestRecordsDBEntities dataContext = new TestRecordsDBEntities();
    string id = ddlGroupId.SelectedValue;

    List<TestRecord> list = dataContext.usp_GetTestRecords(id); //This part doesn't work returns int
    GridView1.DataSource = list;
}
Run Code Online (Sandbox Code Playgroud)

生成的函数 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);
}
Run Code Online (Sandbox Code Playgroud)

Yel*_*nic 26

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

insert into #codes (Code, ActionCodes, Description)
exec TreatmentCodes_sps 0
Run Code Online (Sandbox Code Playgroud)

似乎实体框架对程序应返回的内容感到困惑.我遇到的解决方案是将其添加到sproc的顶部:

SET FMTONLY OFF
Run Code Online (Sandbox Code Playgroud)

在此之后,一切都很好.


蕭為元*_*蕭為元 21

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

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

截图

它应该是你现在需要的.


Rob*_*Rob 14

实体框架无法分辨您的存储过程返回的内容.我成功创建了一个镜像SELECT语句中数据的表变量.只需插入表变量,然后从该表变量中选择.EF应该拿起它.

  • 您能否更清楚地解释一下这部分:“只需插入表变量,然后从该表变量中进行选择。EF 应该选择它。” ?我不知道该怎么办。 (2认同)

wod*_*ode 8

请参阅Ladislav Mrnka在此Stack Overflow帖子中的回答 /sf/answers/499194111/

我有同样的基本问题.

添加

SET FMTONLY OFF
Run Code Online (Sandbox Code Playgroud)

对于您在导入期间尝试导入的过程将解决此问题.除非数据库的目的仅仅是为EF(实体框架)提供模式,否则最好在之后删除该行.

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

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

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

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

when FMTONLY is on:
  1) only the schema is returned (no) rows.
     similar to adding a blanket false statement to your where clause (ie "where 1=0")
  2) flow control statements are ignored

set fmtonly on

if 1=1
begin
    select 1 a
end
else
begin
    select 1 a,2 b
end

while 1=1
select 1 c

以上返回NO行,以及三个查询中的每一个的元数据

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

if 1=0
begin
    set fmtonly off
end

实际上你可以用它来引入跟踪它的逻辑

set fmtonly off
declare @g varchar(30)
set @g = 'fmtonly was set to off'

if 1=0
begin
    set fmtonly off
    set @g = 'fmtonly was set to on' 
end

select @g

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

需要理解的主要概念如下

1. EF turns FMTONLY on to prevent MUTATING data from executing stored procedures
   when it executes them during a model update.
   (from which it follows)

2. setting FMTONLY off in any procedure that EF will attempt to do a schema scan
   (potentially ANY and EACHONE) introduces the potential to mutate database
   data whenever *anyone* attempts to update their database model.


小智 7

如果您的存储过程在结果集中没有主键,实体框架将自动返回一个标量值。因此,您必须在 select 语句中包含一个主键列,或者创建一个带有主键的临时表,以便实体框架为您的存储过程返回一个结果集。