假设以下内容:
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 ...但必须有办法在不必添加的情况下执行此操作不必要的开销或要求我打破存储过程来更新模型?
答案 0 :(得分:59)
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。
答案 1 :(得分:47)
将其添加到存储过程定义的顶部:
SET FMTONLY OFF
允许模型从临时表中推断出架构而不会出现问题。作为奖励,它不需要为合同额外维护。
实施例:
SET FMTONLY OFF
CREATE TABLE #tempTable (
...
)
...
SELECT * FROM #tempTable
答案 2 :(得分:10)
解决方案1 使用表变量而不是临时表。
解决方案2 使用设置FMTONLY关闭;过程中的SQL命令,您将获得列信息以创建新的复杂类型。
解决方案3 这不是一个好方法,但这是一种非常简单的方法。只需添加带有伪数据的select语句,它就不会执行,因为1 = 0。
您可以查看this link
的详细信息答案 3 :(得分: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');