webentwicklung-frage-antwort-db.com.de

Wie übergeben Sie Parameter an die DbContext.Database.ExecuteSqlCommand-Methode?

Nehmen wir an, ich habe ein gültiges Bedürfnis, direkt einen SQL-Befehl in Entity Framework auszuführen. Ich habe Probleme mit der Verwendung von Parametern in meiner SQL-Anweisung. Das folgende Beispiel (nicht mein wirkliches Beispiel) funktioniert nicht.

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

Mit der ExecuteSqlCommand-Methode können Sie keine benannten Parameter wie in ADO.Net übergeben. Die -Dokumentation für diese Methode gibt keine Beispiele für die Ausführung einer parametrisierten Abfrage.

Wie lege ich die Parameter richtig fest?

191
jessegavin

Es stellt sich heraus, dass dies funktioniert.

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

Versuche dies:

var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";

ctx.Database.ExecuteSqlCommand(
    sql,
    new SqlParameter("@FirstName", firstname),
    new SqlParameter("@Id", id));
260
Robert te Kaat

Du kannst entweder:

1) Übergeben Sie rohe Argumente und verwenden Sie die {0} -Syntax. Z.B:

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

2) Übergeben Sie die Argumente der DbParameter-Unterklasse und verwenden Sie die @ParamName-Syntax. 

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

Wenn Sie die erste Syntax verwenden, umgibt EF Ihre Argumente tatsächlich mit DbParamater-Klassen, weist ihnen Namen zu und ersetzt {0} durch den generierten Parameternamen.

Die erste Syntax wird bevorzugt, da Sie keine Factory verwenden müssen oder wissen, welche Art von DbParamaters erstellt werden soll (SqlParameter, OracleParamter usw.).

63
Will Brown

Die anderen Antworten funktionieren nicht, wenn Sie Oracle verwenden. Sie müssen : anstelle von @ verwenden.

var sql = "Update [User] SET FirstName = :FirstName WHERE Id = :Id";

context.Database.ExecuteSqlCommand(
   sql,
   new OracleParameter(":FirstName", firstName), 
   new OracleParameter(":Id", id));
17
Ryan M

Versuchen Sie dies (bearbeitet):

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

Vorherige Idee war falsch. 

16
Ladislav Mrnka

Für Entity Framework Core 2.0 oder höher lautet der korrekte Weg dazu:

var firstName = "John";
var id = 12;
ctx.Database.ExecuteSqlCommand($"Update [User] SET FirstName = {firstName} WHERE Id = {id}";

Beachten Sie, dass Entity Framework die beiden Parameter für Sie erstellt, sodass Sie vor SQL Injection geschützt sind.

Beachten Sie auch, dass es NICHT ist:

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

dies schützt Sie NICHT vor SQL Injection und es werden keine Parameter erzeugt.

das für mehr.

4
Greg Gum

Vereinfachte Version für Oracle. Wenn Sie OracleParameter nicht erstellen möchten

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

ctx.Database.ExecuteSqlCommand(@"Update [User] SET FirstName = {0} WHERE Id = {1}"
, new object[]{ firstName, id });

Das ist so einfach !!!

Bild zum Erkennen der Parameterreferenz

 enter image description here

2
Zaw

Für die async-Methode ("ExecuteSqlCommandAsync") können Sie diese wie folgt verwenden:

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)
    });
2
Magu

Wenn Ihre zugrunde liegenden Datenbankdatentypen varchar sind, sollten Sie den unten angegebenen Ansatz einhalten. Andernfalls hätte die Abfrage große Auswirkungen auf die Leistung.

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

Sie können den SQL-Profiler überprüfen, um den Unterschied zu sehen.

1
akd
public static class DbEx {
    public static IEnumerable<T> SqlQueryPrm<T>(this System.Data.Entity.Database database, string 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<T>(sql, arr);
        }
    }
    private static IDictionary<string, object> ToDictionary(object data) {
        var attr = System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance;
        var dict = new Dictionary<string, object>();
        foreach (var property in data.GetType().GetProperties(attr)) {
            if (property.CanRead) {
                dict.Add(property.Name, property.GetValue(data, null));
            }
        }
        return dict;
    }
}

Verwendungszweck:

var names = db.Database.SqlQueryPrm<string>("select name from position_category where [email protected]_key", new { id_key = "mgr" }).ToList();
1
Neco

Gespeicherte Prozeduren können wie folgt ausgeführt werden

 string cmd = Constants.StoredProcs.usp_AddRoles.ToString() + " @userId, @roleIdList";
                        int result = db.Database
                                       .ExecuteSqlCommand
                                       (
                                          cmd,
                                           new SqlParameter("@userId", userId),
                                           new SqlParameter("@roleIdList", roleId)
                                       );
0

Mehrere Parameter in einer gespeicherten Prozedur mit mehreren Parametern in vb:

Dim result= db.Database.ExecuteSqlCommand("StoredProcedureName @a,@b,@c,@d,@e", a, b, c, d, e)
0
Dani

Für .NET Core 2.2 können Sie FormattableString für dynamisches SQL verwenden.

//Assuming this is your dynamic value and this not coming from user input
var tableName = "LogTable"; 
// let's say target date is coming from user input
var targetDate = DateTime.Now.Date.AddDays(-30);
var param = new SqlParameter("@targetDate", targetDate);  
var sql = string.Format("Delete From {0} Where CreatedDate < @targetDate", tableName);
var froamttedSql = FormattableStringFactory.Create(sql, param);
_db.Database.ExecuteSqlCommand(froamttedSql);
0
Circuit Breaker