3

我有一个 postgresql 数据库,我想做的是在尽可能少的查询中从表中删除一堆行。所以循环不是一个好的选择。我正在为 postgres 驱动程序使用 NPGSQL。

我有下面的代码,但它不起作用。

        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:整数输入语法无效:”错误。有没有办法克服这个问题?如果是的话,我必须使用字符串的第一个删除语句可以做类似的事情吗?

4

1 回答 1

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,稍后再试。

于 2013-08-28T12:56:45.000 回答