41

假设如下:

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

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

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

如何克服这一点?

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

4

4 回答 4

66
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

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

于 2013-05-16T18:20:27.073 回答
53

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

SET FMTONLY OFF
允许模型毫无问题地从临时表中推断模式。作为奖励,它不需要额外的合同维护。

例子:

SET FMTONLY OFF

CREATE TABLE #tempTable (
    ...
)

...

SELECT * FROM #tempTable 
于 2015-06-11T16:02:13.497 回答
10

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

解决方案 2 使用 Set FMTONLY off;程序中的 SQL 命令,您将获得创建新复杂类型的列信息。

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

您可以在此链接上查看详细信息

于 2015-09-03T04:49:00.403 回答
0

这是不完整的,但是当设置 fmtonly off 不起作用时,您可以使用以下命令生成数据协定:

        SELECT * 
        FROM tempdb.sys.columns 
        WHERE [object_id] = OBJECT_ID(N'tempdb..#u');

        select case  system_type_id 
        when 62 then 'cast(null as float) as ' 
        when 175 then 'cast(null as char(' + cast(max_length as varchar(50)) + ')) as ' 
        when 167 then 'cast(null as varchar(' + cast(max_length as varchar(50)) + ')) as ' 
        when 56 then 'cast(null as int) as ' 
        when 104 then 'cast(null as bit) as ' 
        when 106 then 'cast(null as decimal(' + cast(precision as varchar(50)) + ',' + cast(scale as varchar(50)) + ')) as ' 
        when 40 then 'cast(null as date) as '            
        end
        + name + ','
        from  tempdb.sys.columns 
        WHERE [object_id] = OBJECT_ID(N'tempdb..#u');
于 2019-04-09T14:08:21.420 回答