J'ai une procédure stockée qui contient la sélection dynamique. Quelque chose comme ça:
ALTER PROCEDURE [dbo].[usp_GetTestRecords]
--@p1 int = 0,
--@p2 int = 0
@groupId nvarchar(10) = 0
AS
BEGIN
SET NOCOUNT ON;
DECLARE @query NVARCHAR(max)
SET @query = 'SELECT * FROM CUSTOMERS WHERE Id = ' + @groupId
/* This actually contains a dynamic pivot select statement */
EXECUTE(@query);
END
Dans SSMS, la procédure stockée fonctionne correctement et affiche le jeu de résultats.
En C #, en utilisant Entity Framework, il montre le retour d'une int
au lieu de IEnumerable
?
private void LoadTestRecords()
{
TestRecordsDBEntities dataContext = new TestRecordsDBEntities();
string id = ddlGroupId.SelectedValue;
List<TestRecord> list = dataContext.usp_GetTestRecords(id); //This part doesn't work returns int
GridView1.DataSource = list;
}
Fonction générée pour usp_GetTestRecords
public virtual int usp_GetTestRecords(string groupId)
{
var groupIdParameter = groupId != null ?
new ObjectParameter("groupId", groupId) :
new ObjectParameter("groupId", typeof(string));
return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction("usp_GetTestRecords", groupIdParameter);
}
Entity Framework ne peut pas dire ce que votre procédure stockée renvoie. J'ai réussi à créer une variable de table qui reflète les données de votre instruction SELECT. Insérez simplement dans la variable de table puis faites une sélection à partir de cette variable de table. EF devrait le prendre.
Je l'obtiens quand j'ai une procédure stockée qui inclut un appel "exec" dans une table temporaire, telle que:
insert into #codes (Code, ActionCodes, Description)
exec TreatmentCodes_sps 0
Il semble qu'Entity Framework s'embrouille quant à ce qui devrait être renvoyé par la procédure. La solution que j'ai rencontrée consiste à ajouter ceci au sommet du sproc:
SET FMTONLY OFF
Après cela, tout va bien.
J'ai eu le même problème, et trouvé la solution ici
Ce devrait être ce dont vous avez besoin maintenant.
Voir la réponse de Ladislav Mrnka dans cet article Stool Overflow https://stackoverflow.com/a/7131344/4318324
J'ai eu le même problème de base.
Ajouter
SET FMTONLY OFF
Le problème que vous tentez d’importer lors de l’importation au cours de l’importation est corrigé ..____ Il est recommandé de supprimer la ligne ultérieurement, sauf si la base de données a pour seul but de fournir un schéma pour EF (Entity Framework).
La principale raison de prudence est que EF utilise ce paramètre pour empêcher les mutations de données lors de la tentative d'obtention de métadonnées.
Si vous actualisez votre modèle d'entité à partir d'une base de données, toute procédure contenant cette ligne peut potentiellement mettre à jour les données de cette base simplement en essayant d'obtenir le schéma.
Je voulais ajouter une note supplémentaire à ce sujet afin qu'il ne soit pas nécessaire de parcourir intégralement l'autre lien.
si vous voulez essayer d’utiliser FMTONLY, voici quelques points à garder à l’esprit.
lorsque FMTONLY est activé: 1) seul le schéma est renvoyé (non) lignes . similaire à l'ajout d'une déclaration fausse générale à votre clause where (c'est-à-dire "où 1 = 0") 2) les instructions de contrôle de flux sont ignorées
Exemple
mis en permanence sur si 1 = 1 début sélectionnez 1 a end else begin sélectionnez 1 a, 2 b end tandis que 1 = 1 sélectionnez 1 c
Ce qui précède ne renvoie aucune ligne et les métadonnées de chacune des trois requêtes.
Pour cette raison, certaines personnes suggèrent d’en changer en tirant parti du fait qu’il ne respecte pas le contrôle de flux.
si 1 = 0 début mettre finement à off end
En fait, vous pouvez utiliser ceci pour introduire une logique qui suit cette
réglé fmtonly off declare @g varchar (30) set @g = 'fmtonly a été désactivé' si 1 = 0 début régler fmtonly off set @g = 'fmtonly était sur on' end sélectionnez @g
Réfléchissez très attentivement avant d'essayer d'utiliser cette fonctionnalité, car elle est à la fois déconseillée et rend potentiellement extrêmement difficile le suivi de SQL
les principaux concepts à comprendre sont les suivants:
1. EF active FMTONLY pour empêcher la MUTATION de données d’exécuter des procédures stockées quand il les exécute pendant la mise à jour du modèle . (dont il découle) 2. en désactivant FMTONLY dans toute procédure par laquelle EF essaiera de faire une analyse de schéma (potentiellement ANY et EACHONE) introduit le potentiel de mutation de la base de données les données chaque fois que quiconque tente de mettre à jour son modèle de base de données .
Entity Framework renverra automatiquement une valeur scalaire si votre procédure stockée n'a pas de clé primaire dans votre jeu de résultats. Ainsi, vous devez inclure une colonne de clé primaire dans votre instruction select ou créer une table temporaire avec une clé primaire afin qu'Entity Framework renvoie un ensemble de résultats pour votre procédure stockée.
J'ai eu le même problème, j'ai changé le nom des champs de retour par le mot clé 'AS' et j'ai résolu mon problème. Une des raisons de ce problème est l'attribution de noms aux noms de colonnes avec des mots clés réservés SQL Server.
L'exemple est jachères:
ALTER PROCEDURE [dbo].[usp_GetProducts]
AS
BEGIN
SET NOCOUNT ON;
SELECT
, p.Id
, p.Title
, p.Description AS 'Description'
FROM dbo.Products AS p
END
Lorsque vous avez généré votre classe de modèle pour votre procédure stockée, vous avez choisi le résultat du retour scalaire par erreur. vous devez supprimer votre procédure stockée de votre modèle d'entité, puis rajouter la procédure stockée. Dans la boîte de dialogue de la procédure stockée, vous pouvez choisir le type de retour attendu.Ne paséditez simplement le code généré. Cela peut fonctionner maintenant, mais le code généré peut être remplacé si vous apportez d'autres modifications à votre modèle.
J'ai réfléchi un peu à cela et je pense avoir une réponse meilleure/plus simple
Si vous avez un complexe stocké qui rend difficile la structure d'entités (pour les versions actuelles d'Entity Framework qui utilisent la balise FMTONLY pour acquérir le schéma)
pensez à faire ce qui suit au début de votre procédure stockée.
-- où [columnlist] correspond au schéma que vous souhaitez que EF récupère pour votre procédure stockée si 1 = 0 begin sélectionnez [columnlist] de [liste de tables et jointures] .__ où 1 = 0 fin
si vous êtes en mesure de charger votre jeu de résultats dans une variable de tablevous pouvez procéder comme suit pour que votre schéma reste synchronisé
déclarer @tablevar comme table ( blah int , moreblah varchar (20) ) si 1 = 0 début sélectionnez * dans @tablevar end ... -- chargez des données dans @tablevar sélectionnez * dans @tablevar
Eh bien, j’avais ce problème aussi, mais après des heures de recherche en ligne, aucune des méthodes ci-dessus n’a aidé… .. Enfin, j’ai appris que cela se produirait si votre procédure de magasin obtenait des paramètres aussi nuls et générant des erreurs d’exécution des requêtes. Entity Framework générera une méthode pour la procédure de magasin en définissant le modèle d’entité complexe. En raison de cette valeur nulle, votre procédure de magasin renverra une valeur int.
Veuillez vérifier votre procédure de stockage soit en fournissant des résultats vides avec des valeurs null. Cela résoudra votre problème. J'espère.
Si vous avez besoin de faire cela, alors vous feriez peut-être mieux de faire une partie du dbcontext et de créer vous-même la fonction C # qui utilisera SqlQuery pour retourner les données dont vous avez besoin. Les avantages par rapport aux autres options sont les suivants:
Exemple de code:
public partial class myEntities
{
public List<MyClass> usp_GetTestRecords(int _p1, int _p2, string _groupId)
{
// fill out params
SqlParameter p1 = new SqlParameter("@p1", _p1);
...
obj[] parameters = new object[] { p1, p2, groupId };
// call the proc
return this.Database.SqlQuery<MyClass>(@"EXECUTE usp_GetTestRecords @p1, @p2, @groupId", parameters).ToList();
}
}
La meilleure solution que j'ai trouvée est de tricher un peu.
Dans la procédure de magasin, commentez tout, mettez une première ligne avec un select [foo]='', [bar]=''
, etc., mettez à jour le modèle, allez à la fonction mappée, sélectionnez le type complexe et cliquez sur Get Column Information
, puis Create Complex Type
.
Maintenant, commentez la fausse sélection et annulez le commentaire du corps de la procédure de magasin réel.
Pendant l'importation
SET FMTONLY ON Peut être utilisé pour prendre le schéma sp.
Si vous modifiez le sp et souhaitez mettre à jour le nouveau, vous devez supprimer l'ancienne fonction définie du fichier edmx (du xml), car même si vous supprimez le sp du navigateur de modèle, il n'est pas supprimé dans edmx. Par exemple;
<FunctionImport Name="GetInvoiceByNumber" ReturnType="Collection(Model.Invoice_Result)">
<Parameter Name="InvoiceNumber" Mode="In" Type="Int32" />
</FunctionImport>
J'ai eu le même problème, et lorsque je supprime totalement la balise FuctionImport du sp correspondant, le modèle a été mis à jour à droite. Vous pouvez trouver la balise en recherchant le nom de la fonction dans Visual Studio.
Il suffit de changer pour
ALTER PROCEDURE [dbo].[usp_GetTestRecords]
--@p1 int = 0,
--@p2 int = 0
@groupId nvarchar(10) = 0
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM CUSTOMERS WHERE Id = @groupId
END
Je sais que c'est un vieux fil, mais si quelqu'un a les mêmes problèmes, je raconterai mes ennuis.
Pour vous aider à trouver le problème, exécutez SQL Profileer lorsque vous ajoutez votre proc stocké. Ensuite, vous pouvez voir quelle structure d'entité transmet en tant que paramètres afin de générer votre jeu de résultats. J'imagine presque toujours qu'il transmettra des valeurs de paramètre nulles. Si vous générez SQL à la volée en concaténant des valeurs de chaîne et des valeurs de paramètre et que certaines sont nulles, SQL s'interrompra et vous n'obtiendrez pas de jeu de retour.
Je n'ai pas eu besoin de générer des tables temporaires ou quoi que ce soit simplement une commande exec.
J'espère que ça aide
Vous aurez peut-être de la chance en ouvrant le navigateur de modèle, puis en allant à Importations de fonctions, en double-cliquant sur la procédure stockée en question, puis en cliquant manuellement sur "Obtenir les informations sur la colonne", puis sur "Créer un nouveau type de complexe". Cela règle généralement le problème.