我们假设我有一个在Entity Framework中直接执行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中的命名参数,documentation for this method没有提供有关如何执行参数化查询的任何示例。
如何正确指定参数?
答案 0 :(得分:264)
试试这个:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id";
ctx.Database.ExecuteSqlCommand(
sql,
new SqlParameter("@FirstName", firstname),
new SqlParameter("@Id", id));
答案 1 :(得分:209)
事实证明这是有效的。
var firstName = "John";
var id = 12;
var sql = "Update [User] SET FirstName = {0} WHERE Id = {1}";
ctx.Database.ExecuteSqlCommand(sql, firstName, id);
答案 2 :(得分:64)
你可以:
1)传递原始参数并使用{0}语法。 E.g:
DbContext.Database.SqlQuery("StoredProcedureName {0}", paramName);
2)传递DbParameter子类参数并使用@ParamName语法。
DbContext.Database.SqlQuery("StoredProcedureName @ParamName",
new SqlParameter("@ParamName", paramValue);
如果您使用第一种语法,EF实际上会使用DbParamater类包装您的参数,为它们分配名称,并用生成的参数名称替换{0}。
首选语法(如果是首选),因为您不需要使用工厂或知道要创建的DbParamaters类型(SqlParameter,OracleParamter等)。
答案 3 :(得分:18)
使用Oracle时,其他答案无效。您需要使用:
代替@
。
var sql = "Update [User] SET FirstName = :FirstName WHERE Id = :Id";
context.Database.ExecuteSqlCommand(
sql,
new OracleParameter(":FirstName", firstName),
new OracleParameter(":Id", id));
答案 4 :(得分:16)
试试这个(已编辑):
ctx.Database.ExecuteSqlCommand(sql, new SqlParameter("FirstName", firstName),
new SqlParameter("Id", id));
以前的想法是错误的。
答案 5 :(得分:6)
对于实体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的侵害,并且不会产生任何参数。
有关更多信息,请参见this。
答案 6 :(得分:3)
Oracle的简化版。如果您不想创建OracleParameter
var sql = "Update [User] SET FirstName = :p0 WHERE Id = :p1";
context.Database.ExecuteSqlCommand(sql, firstName, id);
答案 7 :(得分:2)
对于async方法(“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)
});
答案 8 :(得分:2)
var firstName = "John";
var id = 12;
ctx.Database.ExecuteSqlCommand(@"Update [User] SET FirstName = {0} WHERE Id = {1}"
, new object[]{ firstName, id });
这很简单!!!
了解参数参考的图片
答案 9 :(得分:1)
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();
答案 10 :(得分: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以查看差异。
答案 11 :(得分:0)
在vb中具有多个参数的存储过程中的多个参数:
Dim result= db.Database.ExecuteSqlCommand("StoredProcedureName @a,@b,@c,@d,@e", a, b, c, d, e)
答案 12 :(得分:0)
存储过程可以如下执行
string cmd = Constants.StoredProcs.usp_AddRoles.ToString() + " @userId, @roleIdList";
int result = db.Database
.ExecuteSqlCommand
(
cmd,
new SqlParameter("@userId", userId),
new SqlParameter("@roleIdList", roleId)
);
答案 13 :(得分:0)
对于.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);