Supposons ce qui suit:
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
Lorsque je génère une fonction import ou mappe un type de retour, EF ne génère pas de type complexe ou me dit:
La procédure ou la fonction stockée sélectionnée ne renvoie aucune colonne
Comment surmonter cela?
D'autres réponses suggèrent en utilisant des variables de table (ne va pas le faire pour des raisons de performances) en simulant le schéma de retour et en commentant la véritable procédure stockée , d'autres suggèrent en faisant similaire avec vues ... mais il doit y avoir un moyen de le faire sans avoir à ajouter des frais généraux inutiles ou à me forcer à interrompre une procédure stockée pour mettre à jour le modèle?
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
Fournir un faux contrat de données pour l'ensemble de résultats est le moyen le plus simple, le plus propre et le plus rapide de résoudre le problème. Ce même problème existe également dans les contrôles de source de données dans SSIS. .NET lira le jeu de résultats à partir de la section "contrat" inaccessible de la requête et fournira les métadonnées pour le type complexe. Aucun impact sur les performances et pas besoin de commenter le SQL qui fait le travail réel.
L'ajout de cela en haut de la définition de procédure stockée:
SET FMTONLY OFF
Exemple:
SET FMTONLY OFF
CREATE TABLE #tempTable (
...
)
...
SELECT * FROM #tempTable
Solution 1 Utilisez une variable de table au lieu d'une table temporaire.
Solution 2 Utilisez le réglage FMTONLY désactivé; Commande SQL dans la procédure et vous obtiendrez les informations de colonne pour créer un nouveau type complexe.
Solution 3 Ce n'est pas un bon moyen, mais c'est un moyen très simple. Ajoutez simplement une instruction select avec des données factices et elle ne s'exécutera pas car 1 = 0.
vous pouvez vérifier les détails sur ce lien
Ceci est incomplet mais lorsque la désactivation de fmtonly ne fonctionne pas, vous pouvez générer le contrat de données à l'aide de ce qui suit:
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');