以下を想定してください:
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は複雑な型を生成しないか、次のように通知します。
選択したストアドプロシージャまたは関数は列を返しません
これを克服する方法は?
テーブル変数を使用 (パフォーマンス上の理由でこれを行わない) リターンスキーマを偽造し、実際のストアドプロシージャをコメントアウトする 、他の提案 同様のことを行うwith views ...しかし、不必要なオーバーヘッドを追加したり、モデルを更新するためにストアドプロシージャを壊す必要なく、これを行う方法が必要ですか?
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をコメント化する必要もありません。
これをストアドプロシージャ定義の先頭に追加します。
SET FMTONLY OFF
例:
SET FMTONLY OFF
CREATE TABLE #tempTable (
...
)
...
SELECT * FROM #tempTable
解決策1一時テーブルの代わりにテーブル変数を使用します。
解決策2 Set FMTONLY off;プロシージャ内のSQLコマンドを実行すると、列情報を取得して新しい複合型を作成します。
解決策3これは良い方法ではありませんが、非常に簡単な方法です。ダミーデータを含むselectステートメントを追加すると、1 = 0であるため実行されません。
このリンク で詳細を確認できます
これは不完全ですが、set 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');