Je crée une nouvelle application qui doit s’interfacer avec le code existant :(.
La procédure stockée que j'essaie d'appeler utilise RETURN pour son résultat. Mes tentatives d'exécution et d'utilisation de la valeur de retour donnent lieu à l'exception:
InvalidOperationException: lors de l'exécution d'une commande, les paramètres doivent être exclusivement des paramètres ou des valeurs de base de données.
Changer le proc stocké pour renvoyer la valeur d'une autre manière n'est pas souhaitable, car cela nécessite soit de mettre à jour l'application existante, soit de maintenir un proc stocké presque dupliqué.
Le synopsis de proc stocké hérité:
DECLARE @MyID INT
INSERT INTO MyTable ...
SELECT @MyID = IDENTITY()
RETURN @MyID
Mon Entity Framework/DbContext fonctionne, ce qui génère l’exception InvalidOperationException ci-dessus.
SqlParameter parm = new SqlParameter() {
ParameterName = "@MyID",
Direction = System.Data.ParameterDirection.ReturnValue
};
DbContext.Database.ExecuteSqlCommand("EXEC dbo.MyProc", parm);
Recherche de toutes les solutions ne nécessitant pas de modification du processus stocké.
Vous pouvez capturer la valeur de retour de la procédure stockée dans un paramètre de sortie:
SqlParameter parm = new SqlParameter() {
ParameterName = "@MyID",
SqlDbType = SqlDbType.Int,
Direction = System.Data.ParameterDirection.Output
};
Database.ExecuteSqlCommand("exec @MyId = dbo.MyProc", parm);
int id = (int)parm.Value;
Vous n'avez pas devez utiliser ExecuteSqlCommand
.
Vous pouvez simplement obtenir la connexion sous-jacente à partir de DbContext.Database.Connection
et utiliser un fichier ADO.NET brut (CreateCommand()
, ExecuteNonQuery()
, ...).
Je sais que c'est un peu tard, mais ça marche pour moi:
var param = new SqlParameter("@Parameter1", txtBoxORsmth.text);
someVariable = ctx.Database.SqlQuery<int>("EXEC dbo.MyProc", param).First();
Le message d'erreur
InvalidOperationException: lors de l'exécution d'une commande, les paramètres doivent être exclusivement des paramètres ou des valeurs de base de données.
signifie que vous ne fournissez pas le bon type (ou quelque chose qui ne figure pas dans votre extrait de code) dans la liste des paramètres de SQLParameters.
Dans mon cas, j'avais oublié de supprimer une MergeOption car j'avais modifié la façon dont la commande SQL était exécutée.
J'ai essayé les méthodes ci-dessus, mais seule cette méthode fonctionne pour moi (doit avoir la fonction 'ToList ()'):
SqlParameter res = new SqlParameter()
{
ParameterName = "Count",
Value=1,
Direction = System.Data.ParameterDirection.Output
};
db.Database.SqlQuery<object>(
"[dbo].[GetWorkerCountBySearchConditions] @Count ,
res
).ToList();
return Convert.ToInt32(res.Value);
Cela retournera l'int depuis un proc stocké utilisant DBContext:
var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First();
Créer une table pour With exemple de paramètre pour tester ou modifier la deuxième requête SQL en fonction de la vôtre.
CREATE TABLE [dbo].[Test](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
// ============================================= ========== //
public void Test()
{
using (var db = new DbContext())
{
string sql = "dbo.MyProc"; //With Out Parameter
int id1 = (int)db.Database.SqlQuery<decimal>(sql).FirstOrDefault();
db.SaveChanges();
//Or
sql = "INSERT Test(Name) values({0}) SELECT SCOPE_IDENTITY();"; //With Parameter
int id2 = (int)db.Database.SqlQuery<decimal>(sql, new object[] { "Thulasi Ram.S" }).FirstOrDefault();
db.SaveChanges();
}
}