可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Let's just suppose I have a valid need for directly executing a sql command in Entity Framework. I am having trouble figuring out how to use parameters in my sql statement. The following example (not my real example) doesn't work.
var firstName = "John"; var id = 12; var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; ctx.Database.ExecuteSqlCommand(sql, firstName, id);
The ExecuteSqlCommand method doesn't allow you to pass in named parameters like in ADO.Net and the documentation for this method doesn't give any examples on how to execute a parameterized query.
How do I specify the parameters correctly?
回答1:
Try this:
var sql = @"Update [User] SET FirstName = @FirstName WHERE Id = @Id"; ctx.Database.ExecuteSqlCommand( sql, new SqlParameter("@FirstName", firstname), new SqlParameter("@Id", id));
回答2:
Turns out that this works.
var firstName = "John"; var id = 12; var sql = "Update [User] SET FirstName = {0} WHERE Id = {1}"; ctx.Database.ExecuteSqlCommand(sql, firstName, id);
回答3:
You can either:
1) Pass raw arguments and use the {0} syntax. E.g:
DbContext.Database.SqlQuery("StoredProcedureName {0}", paramName);
2) Pass DbParameter subclass arguments and use @ParamName syntax.
DbContext.Database.SqlQuery("StoredProcedureName @ParamName", new SqlParameter("@ParamName", paramValue);
If you use the first syntax, EF will actually wrap your arguments with DbParamater classes, assign them names, and replace {0} with the generated parameter name.
The first syntax if preferred because you don't need to use a factory or know what type of DbParamaters to create (SqlParameter, OracleParamter, etc.).
回答4:
Try this (edited):
ctx.Database.ExecuteSqlCommand(sql, new SqlParameter("FirstName", firstName), new SqlParameter("Id", id));
Previous idea was wrong.
回答5:
The other answers don't work when using Oracle. You need to use :
instead of @
.
var sql = "Update [User] SET FirstName = :FirstName WHERE Id = :Id"; context.Database.ExecuteSqlCommand( sql, new OracleParameter(":FirstName", firstName), new OracleParameter(":Id", id));
回答6:
public static class DbEx { public static IEnumerable SqlQueryPrm(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(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();
回答7:
Simplified version for Oracle. If you don't want to create OracleParameter
var sql = "Update [User] SET FirstName = :p0 WHERE Id = :p1"; context.Database.ExecuteSqlCommand(sql, firstName, id);
回答8:
For the async Method ("ExecuteSqlCommandAsync") you can use it like this:
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) });
回答9:
If your underline database data types are varchar then you should stick with teh approach below. Otherwise It would have a huge performance impact.
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);
You can check Sql profiler to see the difference.