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'。実際にはサーバー側の文字列です)になると思います。

DB が SQL サーバーの場合、テーブル値パラメーターを使用できます。配列をパラメーターとして PostgreSQL に渡すことができる可能性があります。後で試す必要があります。

于 2013-08-28T12:56:45.000 に答える