问题
I'm using Entity Framework and I want to perform a bulk update. It is way too inefficient to load each row, update those rows, and then save them back to the database.
So I'd prefer to use DbContext.Database.ExecuteSqlCommand(). But how can I use this method to update all those rows with an ID contained in my list of IDs?
Here's what I have so far.
IEnumerable<int> Ids;
DbContext.Database.ExecuteSqlCommand("UPDATE Messages SET Viewed = 1 WHERE Id IN (@list)", Ids);
I realize I could manually build a string with the correct query, but I'd prefer to pass my parameters as is generally recommended.
Is there any way to make that happen?
回答1:
You can still build the parameters and include them in the parameterized query.
The query would look something like this when generated
UPDATE Messages SET Viewed = 1 WHERE Id IN (@p0, @p1, @p2, ..., @pn)
So given
IEnumerable<int> Ids;
Then
var parameters = Ids.Select((id, index) => new SqlParameter(string.Format("@p{0}", index), id));
var parameterNames = string.Join(", ", parameters.Select(p => p.ParameterName));
var query = string.Format("UPDATE Messages SET Viewed = 1 WHERE Id IN ({0})", parameterNames);
int affected = DbContext.Database.ExecuteSqlCommand(query, parameters.ToArray());
回答2:
Instead of generating query string with exact values, you can generate query string with as many parameters as you have. So you'll get smth like:
DbContext.Database.ExecuteSqlCommand("UPDATE Messages SET Viewed = 1 WHERE Id IN (@p0,@p1,@p2,...,@pN)", Ids);
by smth like this:
var paramsDef = string.Concat(Ids.Select(x=>$"{(Ids.IndexOf(x) > 0 ? "," : "")}p{Ids.IndexOf(x)}"));
DbContext.Database.ExecuteSqlCommand($"UPDATE Messages SET Viewed = 1 WHERE Id IN {paramsDef}", Ids);
Some links I found people doing similar with SqlCommand: http://www.svenbit.com/2014/08/using-sqlparameter-with-sqls-in-clause-in-csharp/ http://nodogmablog.bryanhogan.net/2016/01/parameterize-sql-where-in-clause-c/
来源:https://stackoverflow.com/questions/43969623/setting-where-condition-to-use-ids-contains-in-executesqlcommand