268 votes

Comment utiliser DbContext.Database.SqlQuery<TElement>(sql, params) avec une procédure stockée ? EF Code First CTP5

J'ai une procédure stockée qui a trois paramètres et j'ai essayé d'utiliser ce qui suit pour retourner les résultats :

context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);

J'ai d'abord essayé d'utiliser SqlParameter en tant que paramètres, mais cela n'a pas fonctionné et a généré un message d'erreur. SqlException avec le message suivant :

La procédure ou la fonction 'mySpName' attend le paramètre '@param1', qui n'a pas été fourni.

Ma question est donc de savoir comment utiliser cette méthode avec une procédure stockée qui attend des paramètres ?

Merci.

0 votes

Quelle version de SQL Server utilisez-vous ? J'ai des problèmes avec un code qui fonctionne sur 2008 en mode compat (90), mais lorsque je l'exécute contre 2005, il échoue avec une erreur de syntaxe.

4 votes

@Gats - J'ai eu le même problème avec SQL 2005. Ajoutez "EXEC" avant le nom de la procédure stockée. J'ai posté cette information ici pour référence future : stackoverflow.com/questions/6403930/

416voto

Devart Points 52715

Vous devez fournir les instances SqlParameter de la manière suivante :

context.Database.SqlQuery<myEntityType>(
    "mySpName @param1, @param2, @param3",
    new SqlParameter("param1", param1),
    new SqlParameter("param2", param2),
    new SqlParameter("param3", param3)
);

3 votes

Comment faire pour que cette méthode fonctionne avec les types nullables ? J'ai essayé de le faire avec des décimales nullables, mais lorsque les décimales sont nulles, j'obtiens des erreurs indiquant que le paramètre est manquant. Cependant, la méthode ci-dessous mentionnée par @DanMork fonctionne trouve.

2 votes

Fait passer DbNull.Value au lieu de nulls résout le problème ?

31 votes

Vous pouvez également utiliser la syntaxe \@p# pour éviter d'utiliser SqlParameter comme dans context.Database.SqlQuery<myEntityType("monSpName \@p0, \@p1, \@p2", param1, param2, param3). Source : msdn.microsoft.com/fr-US/data/jj592907 . (Note : j'ai dû utiliser \@@ pour éviter les notifications des utilisateurs, doit être lu sans la barre oblique inversée).

132voto

Dan Mork Points 768

Vous pouvez également utiliser le paramètre "sql" comme spécificateur de format :

context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)

0 votes

Je devais voter pour ça. Même si elle n'a pas été acceptée comme réponse, c'est une solution beaucoup plus facile à écrire que celle qui a été choisie comme réponse.

10 votes

Cette syntaxe me préoccupe un peu. Serait-elle susceptible de faire l'objet d'une injection SQL ? Je suppose que EF exécute "EXEC mySpName @Param1 = ", et qu'il serait possible d'envoyer "x' GO [malicious script" et de causer quelques problèmes ?

10 votes

@TomHalladay aucun risque d'injection SQL - la méthode continuera à citer et à échapper les paramètres en fonction de leur type, de la même manière que les paramètres de style @. Ainsi, pour un paramètre de type chaîne, vous utiliserez "SELECT * FROM Users WHERE email={0}" sans les guillemets dans votre déclaration.

71voto

Tom Halladay Points 2387

Cette solution est (uniquement) pour SQL Server 2005

Vous êtes des sauveurs, mais comme @Dan Mork l'a dit, vous devez ajouter EXEC au mélange. Ce qui m'a fait trébucher était :

  • 'EXEC' avant le nom de la procédure
  • Virgules entre les paramètres
  • Suppression du "@" sur le Param (je ne suis pas sûr que cette partie soit nécessaire).

:

context.Database.SqlQuery<EntityType>(
    "EXEC ProcName @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);

23 votes

+1. Aucune des réponses les plus votées ne comprend exec mais je peux confirmer que j'obtiens une exception si je l'omets.

0 votes

Merci, je recevais une erreur, j'ai ajouté EXEC et l'erreur a disparu. Ce qui est bizarre, c'est que si je faisais context.Database.SqlQuery<EntityType>("ProcName '" + param1 + "','" + param2 + "'") ; cela fonctionnait, mais si j'ajoutais des paramètres, cela ne fonctionnait pas jusqu'à ce que j'ajoute le mot clé EXEC.

2 votes

Pour info : je n'ai pas besoin de la exec mot-clé. +1 pour la suppression du @ sur les paramètres, cela me perturbe toujours.

17voto

ThulasiRam Points 3795
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 });

//Or

using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
}

//Or

using(var context = new MyDataContext())
{
object[] parameters =  { param1, param2, param3 };

return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
parameters).ToList();
}

//Or

using(var context = new MyDataContext())
{  
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
param1, param2, param3).ToList();
}

0 votes

Cela fonctionne pour moi pour l'Assemblée EntityFramework.dll, v4.4.0.0

2 votes

Si vous utilisez (var context = new MyDataContext()) alors .ToList() est obligatoire.

0 votes

J'ai passé un bon moment à découvrir que .ToList() est obligatoire pour obtenir un ensemble de résultats correct.

3voto

Malcolm O'Hare Points 2550

J'utilise cette méthode :

var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);

Je l'aime parce que je n'ai qu'à déposer des Guids et des Datetimes et SqlQuery effectue tout le formatage pour moi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X