Comment passer des parameters à la méthode DbContext.Database.ExecuteSqlCommand?

Supposons simplement que je doive exécuter directement une commande sql dans Entity Framework. J’ai du mal à comprendre comment utiliser les parameters dans mon instruction sql. L’exemple suivant (pas mon exemple réel) ne fonctionne pas.

var firstName = "John"; var id = 12; var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; ctx.Database.ExecuteSqlCommand(sql, firstName, id); 

La méthode ExecuteSqlCommand ne vous permet pas de transmettre des parameters nommés comme dans ADO.Net et la documentation de cette méthode ne donne aucun exemple sur la façon d’exécuter une requête paramétrée.

Comment spécifier les parameters correctement?

    Essaye ça:

     var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; ctx.Database.ExecuteSqlCommand( sql, new SqlParameter("@FirstName", firstname), new SqlParameter("@Id", id)); 

    Il s’avère que cela fonctionne.

     var firstName = "John"; var id = 12; var sql = "Update [User] SET FirstName = {0} WHERE Id = {1}"; ctx.Database.ExecuteSqlCommand(sql, firstName, id); 

    Tu peux soit:

    1) Passez des arguments bruts et utilisez la syntaxe {0}. Par exemple:

     DbContext.Database.SqlQuery("StoredProcedureName {0}", paramName); 

    2) Passez les arguments de sous-classe DbParameter et utilisez la syntaxe @ParamName.

     DbContext.Database.SqlQuery("StoredProcedureName @ParamName", new SqlParameter("@ParamName", paramValue); 

    Si vous utilisez la première syntaxe, EF encapsulera vos arguments dans des classes DbParamater, leur atsortingbuera des noms et remplacera {0} par le nom du paramètre généré.

    La première syntaxe si vous préférez, car vous n’avez pas besoin d’utiliser une fabrique ou de savoir quel type de DbParamaters créer (SqlParameter, OracleParamter, etc.).

    Les autres réponses ne fonctionnent pas avec Oracle. Vous devez utiliser : au lieu de @ .

     var sql = "Update [User] SET FirstName = :FirstName WHERE Id = :Id"; context.Database.ExecuteSqlCommand( sql, new OracleParameter(":FirstName", firstName), new OracleParameter(":Id", id)); 

    Essayez ceci (édité):

     ctx.Database.ExecuteSqlCommand(sql, new SqlParameter("FirstName", firstName), new SqlParameter("Id", id)); 

    L’idée précédente était fausse.

    Version simplifiée pour Oracle. Si vous ne voulez pas créer OracleParameter

     var sql = "Update [User] SET FirstName = :p0 WHERE Id = :p1"; context.Database.ExecuteSqlCommand(sql, firstName, id); 

    Pour la méthode asynchrone (“ExecuteSqlCommandAsync”), vous pouvez l’utiliser comme ceci:

     var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; await ctx.Database.ExecuteSqlCommandAsync( sql, parameters: new[]{ new SqlParameter("@FirstName", firstname), new SqlParameter("@Id", id) }); 
     public static class DbEx { public static IEnumerable SqlQueryPrm(this System.Data.Entity.Database database, ssortingng sql, object parameters) { using (var tmp_cmd = database.Connection.CreateCommand()) { var dict = ToDictionary(parameters); int i = 0; var arr = new object[dict.Count]; foreach (var one_kvp in dict) { var param = tmp_cmd.CreateParameter(); param.ParameterName = one_kvp.Key; if (one_kvp.Value == null) { param.Value = DBNull.Value; } else { param.Value = one_kvp.Value; } arr[i] = param; i++; } return database.SqlQuery(sql, arr); } } private static IDictionary ToDictionary(object data) { var attr = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance; var dict = new Dictionary(); foreach (var property in data.GetType().GetProperties(attr)) { if (property.CanRead) { dict.Add(property.Name, property.GetValue(data, null)); } } return dict; } } 

    Usage:

     var names = db.Database.SqlQueryPrm("select name from position_category where id_key=@id_key", new { id_key = "mgr" }).ToList(); 

    Si vos types de données sous-jacents sont varchar, vous devez suivre l’approche ci-dessous. Sinon, la requête aurait un impact énorme sur les performances.

     var firstName = new SqlParameter("@firstName", System.Data.SqlDbType.VarChar, 20) { Value = "whatever" }; var id = new SqlParameter("@id", System.Data.SqlDbType.Int) { Value = 1 }; ctx.Database.ExecuteSqlCommand(@"Update [User] SET FirstName = @firstName WHERE Id = @id" , firstName, id); 

    Vous pouvez vérifier le profileur SQL pour voir la différence.