240

假设我有在实体框架中直接执行 sql 命令的有效需求。我无法弄清楚如何在我的 sql 语句中使用参数。以下示例(不是我的真实示例)不起作用。

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

ExecuteSqlCommand 方法不允许您像在 ADO.Net 中那样传入命名参数,并且此方法的文档没有提供任何有关如何执行参数化查询的示例。

如何正确指定参数?

4

14 回答 14

324

试试这个:

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

ctx.Database.ExecuteSqlCommand(
    sql,
    new SqlParameter("@FirstName", firstname),
    new SqlParameter("@Id", id));
于 2011-05-20T10:53:09.297 回答
230

事实证明这是有效的。

var firstName = "John";
var id = 12;
var sql = "Update [User] SET FirstName = {0} WHERE Id = {1}";
ctx.Database.ExecuteSqlCommand(sql, firstName, id);
于 2011-03-29T15:42:50.340 回答
72

您可以:

1) 传递原始参数并使用 {0} 语法。例如:

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

2) 传递 DbParameter 子类参数并使用 @ParamName 语法。

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

如果您使用第一种语法,EF 实际上将使用 DbParamater 类包装您的参数,为其分配名称,并将 {0} 替换为生成的参数名称。

如果首选第一种语法,因为您不需要使用工厂或知道要创建哪种类型的 DbParamater(SqlParameter、OracleParamter 等)。

于 2012-05-25T14:26:31.020 回答
22

其他答案在使用 Oracle 时不起作用。您需要使用:而不是@.

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

context.Database.ExecuteSqlCommand(
   sql,
   new OracleParameter(":FirstName", firstName), 
   new OracleParameter(":Id", id));
于 2013-05-30T16:14:22.240 回答
19

试试这个(编辑):

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

以前的想法是错误的。

于 2011-03-29T15:01:11.903 回答
16

对于实体 Framework Core 2.0 或更高版本,正确的做法是:

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

请注意,Entity Framework 将为您生成两个参数,因此您可以免受 Sql Injection 的影响。

另请注意,它不是:

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

因为这不能保护您免受 Sql Injection 的影响,并且不会产生任何参数。

有关更多信息,请参阅

于 2018-10-14T17:25:48.727 回答
4

Oracle 的简化版本。如果您不想创建 OracleParameter

var sql = "Update [User] SET FirstName = :p0 WHERE Id = :p1";
context.Database.ExecuteSqlCommand(sql, firstName, id);
于 2016-10-17T11:47:57.027 回答
4
var firstName = "John";
var id = 12;

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

这太简单了!!!

了解参数参考的图像

在此处输入图像描述

于 2018-09-06T04:43:21.853 回答
3

对于异步方法(“ExecuteSqlCommandAsync”),您可以像这样使用它:

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)
    });
于 2017-05-29T07:20:16.680 回答
1

如果您的基础数据库数据类型是 varchar,那么您应该坚持以下方法。否则查询会对性能产生巨大影响。

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

您可以检查 Sql profiler 以查看差异。

于 2017-05-23T09:28:51.150 回答
0
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;
    }
}

用法:

var names = db.Database.SqlQueryPrm<string>("select name from position_category where id_key=@id_key", new { id_key = "mgr" }).ToList();
于 2012-09-08T00:39:57.683 回答
0

在 vb 中有多个参数的存储过程中的多个参数:

Dim result= db.Database.ExecuteSqlCommand("StoredProcedureName @a,@b,@c,@d,@e", a, b, c, d, e)
于 2018-09-24T11:25:25.917 回答
0

存储过程可以像下面这样执行

 string cmd = Constants.StoredProcs.usp_AddRoles.ToString() + " @userId, @roleIdList";
                        int result = db.Database
                                       .ExecuteSqlCommand
                                       (
                                          cmd,
                                           new SqlParameter("@userId", userId),
                                           new SqlParameter("@roleIdList", roleId)
                                       );
于 2019-03-15T15:32:40.930 回答
-3

对于 .NET Core 2.2,您可以使用FormattableString动态 SQL。

//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);
于 2019-07-29T21:08:37.217 回答