web-dev-qa-db-fra.com

EF ExecuteStoredCommand avec le paramètre ReturnValue

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é.

16
KDrewiske

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;
25
Jeff Ogata

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(), ...).

2
Diego Mijelshon

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();
2
ProToCooL

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.

0
splattne

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);
0
Cedric

Cette méthode extension fera tout le travail sale pour vous maintenant. Voir la description plus complète sur SO ici .

0
Nicholas Petersen

Cela retournera l'int depuis un proc stocké utilisant DBContext:

var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First();
0
garethb

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();
              }
        }
0
Thulasiram