我有一个postgresql数据库,我想要做的是尽可能少的查询从表中删除一堆行。所以循环不是一个好选择。我正在使用NPGSQL作为postgres驱动程序。
我有以下代码,但它无效。
string[] namesToDelete = PromosReplies.
PromosRepliesLoaded.GroupBy(pr => pr.Name).
Select(r=>r.Key).ToArray();
long[] repliesIdsToDelete = context.PromosReplies.
Where(pr => namesToDelete.Contains(pr.Name)).
Select(r => r.Idx).ToArray();
if (repliesIdsToDelete.Length > 0)
{
foreach (var name in namesToDelete)
{
context.Database.ExecuteSqlCommand("DELETE FROM messages WHERE name = {0}", name);
}
string idToDelete = String.Join(",", repliesIdsToDelete);
int result = context.Database.ExecuteSqlCommand(
"DELETE FROM message_translations WHERE idx IN ({0})",
repliesIdsToDelete);
尝试执行上一次查询时出现“错误:22P02:整数的无效输入语法:”错误。有办法克服这个问题吗?如果是,可以使用第一个删除语句,我必须使用字符串?
答案 0 :(得分:4)
<强>更新强> 我不使用EF,但是这里是使用Npgsql作为参数的方法:
var cmd = NpgsqlCommand();
cmd.CommandText = "select * from test where id = any(@list)";
cmd.Connection = "**************************";
cmd.Parameters.Add("list", NpgsqlDbType.Array | NpgsqlDbType.Integer);
cmd.Connection.Open();
var r = cmd.ExecuteReader();
所以我想在EF中它会像:
var par = new NpgsqlParameter("list", NpgsqlDbType.Array | NpgsqlDbType.Text);
var par.Value = namesToDelete;
int result1 = context.Database.ExecuteSqlCommand(
"DELETE FROM messages WHERE name = any(@list)",
par
);
旧我根本不喜欢这个,因为它可能导致SQL注入:
int result1 = context.Database.ExecuteSqlCommand(
String.Format(
"DELETE FROM messages WHERE name in ({0})",
String.Join(",", namesToDelete.Select(x => "'" + x + "'"))
)
);
int result2 = context.Database.ExecuteSqlCommand(
String.Format(
"DELETE FROM message_translations WHERE idx in ({0})",
String.Join(",", repliesIdsToDelete)
)
);
我不是EntityFramework的专家,但我认为当您使用context.Database.ExecuteSqlCommand(command, str)
时,str会被用作参数,因此您的命令会变为DELETE FROM message_translations WHERE idx in ('1, 2, 3, 4')
(请注意单引号,'1, 2, 3, 4'
实际上是服务器端的字符串。)
如果您的数据库是SQL服务器,您可以使用表值参数,也可以将数组作为参数传递到PostgreSQL中,以后再试。