EF4 - la procédure stockée sélectionnée ne renvoie aucune colonne

j'ai requête dans une procédure stockée qui appelle certains serveurs liés avec un certain SQL dynamique. Je comprends que EF n'aime pas cela, donc j'ai spécifiquement énuméré toutes les colonnes qui seraient retournées. Pourtant, elle n'est pas toujours comme ça. Ce que je fais mal? Je veux juste que EF soit capable de détecter les colonnes retournées à partir de la procédure stockée pour que je puisse créer les classes dont j'ai besoin.

s'il vous Plaît voir le code suivant qui fait les dernières lignes de ma procédure stockée:

SELECT
    #TempMain.ID,
    #TempMain.Class_Data,
    #TempMain.Web_Store_Class1,
    #TempMain.Web_Store_Class2,
    #TempMain.Web_Store_Status,
    #TempMain.Cur_1pc_Cat51_Price,
    #TempMain.Cur_1pc_Cat52_Price,
    #TempMain.Cur_1pc_Cat61_Price,
    #TempMain.Cur_1pc_Cat62_Price,
    #TempMain.Cur_1pc_Cat63_Price,
    #TempMain.Flat_Length,
    #TempMain.Flat_Width,
    #TempMain.Item_Height,
    #TempMain.Item_Weight,
    #TempMain.Um,
    #TempMain.Lead_Time_Code,
    #TempMain.Wp_Image_Nme,
    #TempMain.Wp_Mod_Dte,
    #TempMain.Catalog_Price_Chg_Dt,
    #TempMain.Description,
    #TempMain.Supersede_Ctl,
    #TempMain.Supersede_Pn,
    TempDesc.Cust_Desc,
    TempMfgr.Mfgr_Item_Nbr,
    TempMfgr.Mfgr_Name,
    TempMfgr.Vendor_ID
FROM
    #TempMain
        LEFT JOIN TempDesc ON #TempMain.ID = TempDesc.ID
        LEFT JOIN TempMfgr ON #TempMain.ID = TempMfgr.ID
58
demandé sur cjbarth 2011-08-20 04:35:48

13 réponses

EF ne supporte pas l'importation de procédures stockées qui construisent un jeu de résultats à partir de:

  • requêtes dynamiques
  • tables temporaires

la raison est que pour importer la procédure EF doit l'exécuter . Une telle opération peut être dangereuse car elle peut déclencher certaines modifications dans la base de données. À cause de cela, EF utilise la commande spéciale SQL avant d'exécuter la procédure stockée.:

SET FMTONLY ON

en exécutant cette procédure stockée de commande retournera seulement des" métadonnées " au sujet des colonnes dans son ensemble de résultats et il n'exécutera pas sa logique. Mais parce que la logique n'a pas été exécutée il n'y a pas de table temporaire (ou de requête dynamique construite) donc les métadonnées ne contiennent rien.

vous avez deux choix (sauf celui qui nécessite de réécrire votre procédure stockée pour ne pas utiliser ces fonctionnalités):

  • définit retourné le type complexe manuellement (je suppose que cela devrait fonctionner)
  • utilisez un hack et juste pour ajouter la procédure stockée mis à son début SET FMTONLY OFF . Cela permettra au reste du code de votre SP de s'exécuter normalement. Assurez-vous simplement que votre SP ne modifie aucune donnée car ces modifications seront exécutées lors de l'importation! Après l'importation réussie supprimez ce piratage.
139
répondu Ladislav Mrnka 2014-08-06 20:28:49
25
répondu Muhammad Omar ElShourbagy 2017-05-23 12:34:27

ou vous pouvez créer un type de Table défini par L'Utilisateur et le retourner.

CREATE TYPE T1 AS TABLE 
( ID bigint NOT NULL
  ,Field1 varchar(max) COLLATE Latin1_General_CI_AI NOT NULL
  ,Field2 bit NOT NULL
  ,Field3 varchar(500) NOT NULL
  );
GO

puis dans la procédure:

DECLARE @tempTable dbo.T1

INSERT @tempTable (ID, Field1, Field2, Field3)
SELECT .....

....

SELECT * FROM @tempTable

maintenant EF devrait être capable de reconnaître le type de colonnes retournées.

12
répondu Mauricio Ramalho 2013-11-13 14:37:23

comme d'autres l'ont fait remarquer, assurez-vous que la procédure fonctionne réellement. En particulier, dans mon cas, J'exécutais la procédure heureusement sans erreur dans SQL Server Management Studio oubliant complètement que j'étais connecté avec des droits d'administration. Dès que j'ai essayé d'exécuter la procédure en utilisant l'utilisateur principal de mon application, j'ai trouvé qu'il y avait une table dans la requête que cet utilisateur n'avait pas la permission d'accéder.

2
répondu Chris Matthews 2015-08-28 22:08:19

ce que j'ajouterais est:

que l'importation échoue également si les procédures stockées ont des paramètres et ne renvoie aucun résultat défini pour les valeurs par défaut des paramètres.

ma procédure stockée avait 2 paramètres de flotteur et ne retournerait rien quand les deux paramètres sont 0.

afin d'ajouter cette procédure stockée pour le modèle d'entité, j'ai défini la valeur de ces paramètres dans la procédure stockée, de sorte qu'il est garanti à renvoie quelques lignes, quels que soient les paramètres.

ensuite, après avoir ajouté cette procédure stockée au modèle d'entité, je défais les changements.

1
répondu tmanthey 2012-08-28 19:49:59

note intéressante: avait le même problème que j'ai d'abord résolu en utilisant des Variables de Table, plutôt que des Tables de température (juste pour l'importation). Ce n'était pas particulièrement intuitif pour moi, et m'a mis à l'écart en observant initialement mes deux SProcs: l'un utilisant des tables de température et l'autre avec des Variables de Table.

(SET FMTONLY OFF n'a jamais fonctionné pour moi, donc j'ai juste changé mes SProcs temporairement pour obtenir les informations de la colonne, plutôt que de s'embêter avec le hack sur le côté EF tout comme un FYI.)

Ma meilleure option était vraiment juste créer manuellement le type complexe et la cartographie de la fonction Importer à elle. Fonctionnait bien, et la seule différence a fini par être qu'un FactoryMethod supplémentaire pour créer les propriétés a été inclus dans le concepteur.

1
répondu 2012-09-08 01:36:52

les deux solutions : 1-Définir le type de complexe retourné manuellement (je suppose que cela devrait fonctionner) 2-Utilisez un hack et juste pour ajouter la procédure stockée mis à son début mis FMTONLY OFF.

ne pas travailler avec moi dans une procédure, mais il a travaillé avec l'autre!

ma procédure se termine par cette ligne:

SELECT machineId, production [AProduction]
        , (select production FROM #ShiftBFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [BProduction]
        , (select production FROM #ShiftCFinalProd WHERE machineId = #ShiftAFinalProd.machineId) [CProduction]
     FROM #ShiftAFinalProd
     ORDER BY machineId

Merci

1
répondu Ahmed Mostafa 2014-05-26 23:42:42

en plus de ce que @tmanthley a dit, assurez-vous que votre procédure stockée fonctionne réellement en l'exécutant d'abord dans SSMS. J'avais importé quelques procédures stockées et oublié quelques fonctions scalaires dépendantes, ce qui a amené EF à déterminer que la procédure ne retournait pas de colonnes. On dirait une erreur que j'aurais dû attraper plus tôt, mais EF ne vous donne pas de message d'erreur dans ce cas.

1
répondu Derreck Dean 2014-07-29 20:25:52

dans mon cas ajouter SET NOCOUNT ON; en haut de la procédure a résolu le problème. C'est la meilleure pratique de toute façon.

0
répondu Endrju 2015-02-16 11:09:57

dans mon cas, SET FMTONLY OFF n'a pas fonctionné. La méthode que j'ai suivie est, j'ai pris la sauvegarde de la procédure stockée originale et remplacer par seulement le nom de la colonne comme la requête ci-dessous.

Select Convert(max,'') as Id,Convert(max,'') as Name

après ce changement, créer une nouvelle fonction d'importation, le type complexe dans le cadre d'entité. Une fois que la fonction import et le type complexe sont créés, remplacez la requête ci-dessus par votre procédure stockée originale.

0
répondu Darshan Jadyal 2016-03-22 07:19:30
SET FMTONLY OFF 

a travaillé pour moi pour l'une des procédures mais a échoué pour les autres. Les étapes suivantes m'aident à résoudre mon problème

  1. dans le cadre d'une procédure stockée, j'ai créé une table temporaire avec le même type de colonne et inséré toutes les données retournées par requête dynamique à la table temp. et sélectionné les données de la table de température.

    Create table #temp
    (
       -- columns with same types as dynamic query    
    )
    
    EXEC sp_executeSQL @sql 
    
    insert into #temp 
        Select * from #temp 
    
    drop table #temp
    
  2. supprimé type complexe existant, importation fonction et instance de procédure stockée pour l'ancienne procédure stockée et le modèle d'entité mis à jour pour la nouvelle procédure actuelle.

  3. éditez la fonction importée dans entity modal pour le type complexe désiré, vous y obtiendrez toutes les informations de colonne qui n'est pas obtenu pour la procédure stockée précédente.

  4. une fois que vous avez fait avec la création de type, vous pouvez supprimer la table temporaire de la procédure stockée et puis actualiser Entity Framework.

0
répondu PVIJAY 2016-12-17 21:52:58

dans Entity framework, tout en obtenant des informations sur les colonnes, le sql exécute la procédure en passant des valeurs nulles dans le paramètre. Donc j'ai géré le cas null différemment en créant une table temp avec toutes les colonnes requises et en retournant toutes les colonnes avec aucune valeur quand null est passé à la procédure.

dans ma procédure il y avait requête dynamique, quelque chose comme

declare @category_id    int
set @category_id = (SELECT CATEGORY_ID FROM CORE_USER where USER_ID = @USER_ID)
declare @tableName varchar(15)
declare @sql VARCHAR(max)     
declare  @USER_IDT  varchar(100)    
declare @SESSION_IDT  varchar(10)

 IF (@category_id = 3)     
set @tableName =  'STUD_STUDENT'
else if(@category_id = 4)
set @tableName = 'STUD_GUARDIAN'


if isnull(@tableName,'')<>'' 
begin

set @sql  = 'SELECT  [USER_ID], [FIRST_NAME], SCHOOL_NAME, SOCIETY_NAME, SCHOOL_ID,
SESSION_ID, [START_DATE], [END_DATE]
from  @tableName
....
EXECUTE   (@sql)
END

ELSE
BEGIN
SELECT  * from #UserPrfTemp
END

Je ne recevais pas les informations de la colonne dans mon cas après utiliser le jeu FMTONLY OFF trick.

c'est la table temporaire que j'ai créée pour obtenir les données Vierges. Maintenant je reçois la colonne info

Create table #UserPrfTemp
(
[USER_ID] bigint, 
[FIRST_NAME] nvarchar(60),
SCHOOL_NAME nvarchar(60),
SOCIETY_NAME nvarchar(200)
.....
}
0
répondu Rajdeep 2017-01-17 09:58:44

Entity Framework va essayer d'obtenir les colonnes en exécutant votre procédure stockée, en passant NULL pour chaque argument.

  1. S'il vous plaît assurez-vous que la procédure stockée retournera quelque chose dans toutes les circonstances. Note qu'il aurait été plus intelligent d'Entity Framework pour exécuter la procédure stockée avec des valeurs par défaut pour les arguments, par opposition à des valeurs Null.

  2. ER fait ce qui suit pour obtenir le métadonnées de la table:

    SET FMTONLY ON

  3. cela cassera votre procédure stockée dans diverses circonstances, en particulier, si elle utilise une table temporaire.

  4. ainsi pour obtenir un résultat en tant que type complexe; s'il vous plaît essayer en ajoutant

    SET FMTONLY OFF;

Cela a fonctionné pour moi - espérons que cela fonctionne pour vous aussi.

référé de https://social.msdn.microsoft.com/Forums/en-US/e7f598a2-6827-4b27-a09d-aefe733b48e6/entity-model-add-function-import-stored-procedure-returns-no-columns?forum=adodotnetentityframework

0
répondu Kiran Nandan 2018-05-22 12:21:20