EF无法从#temp表中选择存储过程中的返回模式

Joe*_*aus 37 stored-procedures entity-framework temp-tables

假设如下:

CREATE PROCEDURE [MySPROC]
AS 
BEGIN

CREATE TABLE #tempSubset(
    [MyPrimaryKey] [bigint]  NOT NULL,
    [OtherColumn]  [int]     NOT NULL)

INSERT INTO #tempSubset (MyPrimaryKey, OtherColumn) 
    SELECT SomePrimaryKey, SomeColumn 
    FROM   SomeHugeTable
    WHERE  LimitingCondition = true

SELECT MyPrimaryKey, OtherColumn 
FROM   #tempSubset
WHERE  SomeExpensiveCondition = true

END
Run Code Online (Sandbox Code Playgroud)

当我生成函数导入或映射返回类型时,EF不会生成复杂类型或告诉我:

选定的存储过程或函数不返回任何列

怎么克服这个?

其他答案建议使用表变量(由于性能原因不会这样做)伪造返回模式并注释掉实际存储过程,其他建议与视图类似 ...但必须有一种方法来做到这一点,而不必添加不必要的开销或要求我打破存储过程来更新模型?

小智 61

CREATE PROCEDURE [MySPROC]
AS 
BEGIN

--supplying a data contract
IF 1 = 2 BEGIN
    SELECT
        cast(null as bigint)  as MyPrimaryKey,
        cast(null as int)    as OtherColumn
    WHERE
        1 = 2  
END

CREATE TABLE #tempSubset(
    [MyPrimaryKey] [bigint]  NOT NULL,
    [OtherColumn]  [int]     NOT NULL)

INSERT INTO #tempSubset (MyPrimaryKey, OtherColumn) 
    SELECT SomePrimaryKey, SomeColumn 
    FROM   SomeHugeTable
    WHERE  LimitingCondition = true

SELECT MyPrimaryKey, OtherColumn 
FROM   #tempSubset
WHERE  SomeExpensiveCondition = true

END
Run Code Online (Sandbox Code Playgroud)

为结果集提供虚假数据合同是解决问题的最简单,最干净,最快捷的方法.SSIS中的数据源控件也存在同样的问题..NET将从查询的无法访问的"合同"部分读取结果集,并提供复杂类型的元数据.没有性能影响,也没有必要注释掉执行实际工作的SQL.

  • 请注意,如果在模型中生成复杂类型,则在以此格式提供数据协定后,属性将可为空,即'public Nullable <int> MyProperty {get; 组;})'.这很好,因为它将处理db列值为null的情况.如果您在合同中执行类似'SELECT 1 AS [MyProperty column]'的操作,则该属性将为'public int MyProperty {get; 组; ''(你必须删除[sproc] _Result类+复杂类型和regen复杂类型才能看到底层sProc的变化).无论是或依赖于您的情况,请注意. (4认同)

Rom*_*rai 47

将其添加到存储过程定义的顶部:

SET FMTONLY OFF
Run Code Online (Sandbox Code Playgroud)允许模型从临时表中推断出架构而没有问题.作为奖励,它不需要对合同进行额外维护.

例:

SET FMTONLY OFF

CREATE TABLE #tempTable (
    ...
)

...

SELECT * FROM #tempTable 
Run Code Online (Sandbox Code Playgroud)


小智 10

解决方案1使用表变量而不是临时表.

解决方案2使用关闭设置FMTONLY; 过程中的SQL命令,您将获得列信息以创建新的复杂类型.

解决方案3这不是一个好方法,但这是一种非常简单的方法.只需添加一个带有伪数据的select语句,它就不会执行,因为1 = 0.

你可以查看这个链接的详细信息