EF 无法从 #temp 表中选择的存储过程推断返回模式
Posted
技术标签:
【中文标题】EF 无法从 #temp 表中选择的存储过程推断返回模式【英文标题】:EF can't infer return schema from Stored Procedure selecting from a #temp table 【发布时间】:2013-05-11 16:52:00 【问题描述】:假设如下:
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 不会生成复杂类型或告诉我:
选定的存储过程或函数不返回任何列
如何克服这个问题?
其他答案建议using table variables(出于性能原因不会这样做)faking the return schema and commenting out the real stored procedure,其他建议doing similar with views...但必须有一种方法可以做到这一点,而不必增加不必要的开销或要求我这样做打破存储过程来更新模型?
【问题讨论】:
【参考方案1】: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。
【讨论】:
效果很好,比那些替代品好得多!谢谢;) 已经过测试,效果很好!将添加到我用来生成 CREATE PROCEDURES 的脚本中 请注意,如果您在模型中生成复杂类型,在提供此格式的数据协定后,属性将为空,即 'public NullabletrEND
是否应该是true
。【参考方案2】:
将此添加到存储过程定义的顶部:
SET FMTONLY OFF
允许模型从临时表中推断模式而不会出现问题。作为奖励,它不需要额外的合同维护。
示例:
SET FMTONLY OFF
CREATE TABLE #tempTable (
...
)
...
SELECT * FROM #tempTable
【讨论】:
绝对是最简单最快的解决方案。谢谢。 谢谢。更清洁的解决方案。 理想的解决方案。无需像所选答案那样创建虚拟查询 非常简单的灵魂。谢谢,-Xipooo【参考方案3】:解决方案 1 使用表变量而不是临时表。
解决方案 2 使用设置 FMTONLY 关闭;过程中的 SQL 命令,您将获得创建新复杂类型的列信息。
解决方案 3 这不是一个好方法,但它是一个非常简单的方法。只需添加一个带有虚拟数据的 select 语句,它不会执行,因为 1=0。
您可以在this link查看详细信息
【讨论】:
我已经尝试了所有 3 种方法。他们都没有工作。因为我总是迟到 2 天,我为此花了 2 个小时。我需要继续前进。我的临时解决方案是查看模型详细信息以更改复合类型(查找过程和变量)并手动从 int32 更改为 string。这是个坏主意。如果刷新,它将丢失。我什至无法记录它以提醒其他开发人员。任何人都知道会发生什么。请让大家知道。我正在使用 VS 2015、EF 6、SQL Server 2016。TX【参考方案4】:这是不完整的,但是当设置 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');
【讨论】:
以上是关于EF 无法从 #temp 表中选择的存储过程推断返回模式的主要内容,如果未能解决你的问题,请参考以下文章