OleDbCommand с «где в» и dbParameter

Я пытаюсь удалить некоторые строки из таблицы в файле базы данных доступа через С#. Эта попытка завершается без ошибок, что приводит меня к выводу, что у меня есть правильный запрос с неверными данными.

Я попытался посмотреть, могу ли я запросить данные с помощью оператора select из моего кода, и я могу сузить проблему до параметров.

Заявление должно выглядеть следующим образом

SELECT * FROM tbIndex where pguid in ('4a651816-e15b-4c6a-85c4-74033ca6c423', '0add7bff-a22f-4238-9c7f-e1ff4ed3c7e2', '742fae8b-2692-4a6f-802c-848fad570696', '5e6b65de-2403-4800-a47d-e57c7bd8e0a6')

Я пробовал два разных способа*(dbCmd2 и dbCmd3)*, из которых первый*(dbCmd2)* работает, но из-за проблем с инъекциями это не мое предпочтительное решение.

using (OleDbCommand dbCmd2 = new OleDbCommand { Connection = m_Connection })
{
    dbCmd2.CommandText = "SELECT * FROM tbIndex where pguid in ("+pguid+")";
    using (DbDataReader reader = dbCmd2.ExecuteReader())
    {
        List<object[]> readValuesFromIndex = new List<object[]>();
        while (reader.Read())
        {
            //Point reached
            object[] arr = new object[reader.VisibleFieldCount];
            reader.GetValues(arr);
            //...
        }
        reader.Close();
    }

    using (OleDbCommand dbCmd3 = new OleDbCommand { Connection = m_Connection })
    {
        dbCmd3.CommandText = "SELECT * FROM tbIndex where pguid in (@pguid)";
        dbCmd3.Parameters.Add("@pguid", OleDbType.VarChar).Value = pguid;
        using (DbDataReader reader = dbCmd3.ExecuteReader())
        {
            List<object[]> readValuesFromIndex = new List<object[]>();
            while (reader.Read())
            {
                //Point not reached
                object[] arr = new object[reader.VisibleFieldCount];
                reader.GetValues(arr);
                //...
            }
            reader.Close();
        }
    }

Обратите внимание, что pguid установлено на "'4a651816-e15b-4c6a-85c4-74033ca6c423', '0add7bff-a22f-4238-9c7f-e1ff4ed3c7e2', '742fae8b-2692-4a6f-802c-848fad570696', '5e6b65de-2403-4800-a47d-e57c7bd8e0a6'".

Я всегда думал, что второй вариант просто заменит параметр безопасным образом, но это явно не так.

Мой вопрос: Почему второй вариант не возвращает никаких значений?


person Bongo    schedule 07.01.2019    source источник
comment
Первый запрос открыт для SQL-инъекций, поэтому его нельзя использовать. Второй почти наверняка не сработает.   -  person mjwills    schedule 07.01.2019
comment
PetaPoco и другие ORM имеют встроенную поддержку предложений IN (redeyedmonster.co.uk/petapoco-documentation - When using a WHERE IN clause). Вы рассматривали это как вариант здесь?   -  person mjwills    schedule 07.01.2019
comment
Вы думаете, что запрашиваете сервер, чтобы он соответствовал любой из записей в '4a651816-e15b-4c6a-85c4-74033ca6c423', '0add7bff-a22f-4238-9c7f-e1ff4ed3c7e2', '742fae8b-2692-4a6f-802c-848fad570696', '5e6b65de-2403-4800-a47d-e57c7bd8e0a6'. Но на самом деле вы на самом деле просите, чтобы он соответствовал любой из набора записей. Увы, единственной (и единственной) записью в этом наборе является '4a651816-e15b-4c6a-85c4-74033ca6c423', '0add7bff-a22f-4238-9c7f-e1ff4ed3c7e2', '742fae8b-2692-4a6f-802c-848fad570696', '5e6b65de-2403-4800-a47d-e57c7bd8e0a6' (обратите внимание, что это одна строка, а не четыре строки).   -  person mjwills    schedule 07.01.2019
comment
Итак, вам нужно передать не один параметр, как вы это делаете. Вам нужно передать четыре параметра (по одному для каждой строки). PetaPoco и другие ORM сделают это за вас автоматически.   -  person mjwills    schedule 07.01.2019


Ответы (1)


Параметр всегда представляет собой одиночное значение.

Предложение in требует нескольких значений, разделенных запятыми.

Вы можете сделать что-то вроде следующего, чтобы передать их как отдельные параметры:

string[] guids = pguid.Split(',');
string sqlin = "";
int paramno = -1;
foreach (var guid in guids)
{
   parametercount ++;
   sqlin = sqlin + "@Param" + (string)parametercount; + ","
}
dbCmd3.CommandText = "SELECT * FROM tbIndex where pguid in (" + sqlin.Substring(0, sqlin.Length-1) + ")";
for(int i = 0; i <= parametercount; i++){
    dbCmd3.Parameters.Add("@Param" + (string)i, OleDbType.VarChar).Value = guids[i].Replace("'", "");
}
person Erik A    schedule 07.01.2019
comment
Также рассмотрите возможность использования Enumerable.Range и string.Join, чтобы избежать необходимости перебирать guids для создания params. - person mjwills; 07.01.2019
comment
Спасибо. Ваш ответ правильный, поэтому +1. Поскольку @mjwills первым написал ответ в комментариях, я бы пометил его ответ как принятый, если mjwills не напишет ответ, я сделаю его принятым ответом. - person Bongo; 07.01.2019