Entity framework EF无法从临时表中选择的存储过程推断返回模式

Entity framework EF无法从临时表中选择的存储过程推断返回模式,entity-framework,stored-procedures,temp-tables,Entity Framework,Stored Procedures,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

假设如下:

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
        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');
当我生成函数导入或映射返回类型时,EF不会生成复杂类型或告诉我:

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

如何克服这个问题

其他答案建议出于性能原因不要这样做,其他答案建议。。。但是必须有一种方法可以做到这一点,而不必增加不必要的开销,或者要求我破坏存储过程来更新模型

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将从查询的unreachable contract部分读取结果集,并为复杂类型提供元数据。没有性能影响,也不需要注释掉执行实际工作的SQL。

将此添加到存储过程定义的顶部:允许模型从临时表推断架构而不会出现问题。作为奖励,合同不需要额外维护

SET FMTONLY OFF
例如:

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

解决方案2 使用Set FMTONLY off(自动关闭)功能;SQL命令,您将获得列信息以创建新的复杂类型

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


您可以检查

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

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
        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');

工作得很好,比那些替代品好多了!谢谢经过测试,效果非常好!将添加到用于生成创建过程的脚本请注意,如果在模型中生成复杂类型,在提供此格式的数据协定后,属性将为空,即“public nullable MyProperty{get;set;}”。这很好,因为它将处理db列值为null的情况。如果在协定中执行类似于“选择1作为[MyProperty column]”的操作,则属性将是“public int MyProperty{get;set;}”,您必须实际删除[sproc]\u结果类+复杂类型和regen复杂类型,才能看到基础存储过程中的更改。或者取决于你的情况,只是要注意。嘿,嗜睡者和BrianKrahenbuhl非常感谢你的解决方案。这对我很有效。我想知道答案中的趋势是否应该是真的。这绝对是最简单、最快的解决方案。谢谢,谢谢。更干净的溶液。理想的溶液。不需要像在selected answervery simple解决方案中那样创建虚拟查询。谢谢,-XipoooI已经尝试了所有3种方法。他们都没有工作。因为我总是迟到两天,我为此花了两个小时。我需要继续前进。我的临时解决方案是查看模型详细信息,以更改复合类型,找到过程和变量,并手动将int32更改为string。这是个坏主意。如果刷新,它将丢失。我甚至不能记录它来提醒其他开发人员。任何人都知道会发生什么。请让每个人都知道。我使用的是VS 2015、EF 6和SQL server 2016。德克萨斯州