У меня есть список BuilderString, который я хочу содержать данные

 public  List<int> IDS = new List<int>();

 public List<StringBuilder> Items = new List<StringBuilder>(); 

Что не так с этим кодом?

SqlConnection con2 = new SqlConnection("Data Source=aya-PC\\SQLEXPRESS;Initial Catalog=ItemSet;Integrated Security=True");
SqlDataReader rdr2;
SqlCommand cmd2;

con2.Open();

for (int i = 0; i < IDS.Count; i++)
{
    cmd2 = new SqlCommand("select item From TransactiontData where idT=@IDS[i]", con2);
    cmd2.CommandType = CommandType.Text;
    rdr2 = cmd2.ExecuteReader();
    SqlParameter param = new SqlParameter();
    param.ParameterName = "@IDS[i]"

    while (rdr2.Read())
    {
        Items[i].Append((StringBuilder)rdr2["item"]);
    }
} 
0
Aya Ahmed 8 Ноя 2014 в 18:55

2 ответа

Вам нужно немного изменить код:

using (SqlConnection con2 = new SqlConnection("Data Source=aya-PC\\SQLEXPRESS;Initial Catalog=ItemSet;Integrated Security=True"))
using (SqlCommand cmd2 = new SqlCommand("select item From TransactiontData where idT = @IDS", con2))
{
   // add the paramter to the command
   cmd2.Parameter.Add("@IDS", SqlDbType.Int);

   con2.Open();

   for (int i = 0; i < IDS.Count; i++)
   {
       // set the parameter value
       cmd2.Parameter["@IDS"].Value = IDS[i];

       // only *THEN* call ExecuteReader()
       using (SqlDataReader rdr2 = cmd2.ExecuteReader())
       {
              while (rdr2.Read())
              {
                  // **NOT SURE** what you're trying to do here.....
                  // First of all, you need to just call Items.Add()
                  // to add new items to the list - and I'm TOTALLY
                  // UNCLEAR what you're trying to do casting the reader
                  // value to a StringBuilder.......
                  // 
                  // Items[i].Append((StringBuilder)rdr2["item"]);
                  //
                  // replaced with what *might* make more sense.....
                  Items.Add(rdr2["item"].ToString());
              }

              rdr.Close();
       }
    }        

    con2.Close(); 
} 

На заметку:

  • Я бы рекомендовал всегда помещать ваши SqlConnection, SqlCommand и SqlDataReader в блоки using() {...}, чтобы обеспечить правильную утилизацию.

  • вам нужно добавить свой параметр и установить его значение ДО вызова .ExecuteReader()!

  • Поскольку сам запрос никогда не меняется, нет смысла создавать новый SqlCommand на каждой итерации. Создайте команду один раз, а затем просто установите параметр значение (единственное, что меняется) один раз за итерацию.

1
marc_s 9 Ноя 2014 в 11:13
Есть ошибка с диапазоном списка "Индекс был вне допустимого диапазона. Должен быть неотрицательным и меньше размера коллекции".
 – 
Aya Ahmed
8 Ноя 2014 в 19:32
Лучше всего/работает комбинация/объединение этого ответа и другого ответа от @DanGuzman-SQLServerMVP. Для этого ответа: 1) установка cmd2.Parameter["@IDS"].Value должна быть IDS[i], 2) скорее всего, не нужно некоторое время вокруг rdr2.Read(), 3) коллекция Items не у вас еще нет элементов, поэтому вам нужно использовать Items.Add(), а не ссылаться через Items[i], 4) я не думаю, что вы можете (или должны) напрямую приводить к StringBuilder, поскольку входящее значение на самом деле просто строка, и 5), вероятно, должен иметь con2.Close() после цикла for.
 – 
Solomon Rutzky
8 Ноя 2014 в 20:56
@srutzky: (1): нет, проверьте мой ответ - имя параметра в моем ответе IS просто @IDS - нет смысла индексировать этот параметр name.... и (5) - не обязательно, так как блоки using() {...} обеспечивают правильное удаление (и, следовательно, закрытие) соединения
 – 
marc_s
9 Ноя 2014 в 01:47
Марк, ты неправильно понял, что я имел в виду в отношении № 1. Я не имел в виду имя параметра. Я имею в виду передаваемое значение. Ваше имя параметра верное. Но вы передаете значение индекса только i, но переменная C# IDS представляет собой набор целых чисел, поэтому вам нужно использовать переменную индекса i, чтобы получить соответствующий элемент коллекции IDS (иначе вам понадобится цикл foreach). Что касается № 5, я думал, что вы могли бы сказать это ;-), но я заметил, что вы закрыли SqlDataReader, поэтому я решил, что было бы разумно также закрыть соединение :). Но да, второстепенный момент.
 – 
Solomon Rutzky
9 Ноя 2014 в 01:59

Вам нужно присвоить значение параметра в коде приложения, а не в запросе. Я не совсем уверен, чего вы пытаетесь достичь, приведя значение столбца как StringBuilder. Предполагая, что каждый элемент StringBuilder должен содержать одну строку, полученную из столбца varchar/nvarchar, приведенный ниже пример сделает это.

 for (int i = 0; i < IDS.Count; i++)
 {
        var cmd2 = new SqlCommand("select item From TransactiontData where idT=@IDS", con2);

        SqlParameter param = new SqlParameter("@IDS", SqlDbType.Int) { Value = IDS[i] };

        var rdr2 = cmd2.ExecuteReader();

        while (rdr2.Read())
        {
            Items.Add(new StringBuilder((string)rdr2["item"]));
        }
 } 
0
Dan Guzman 8 Ноя 2014 в 20:19
Есть проблема с индексом списка "Индекс был вне допустимого диапазона. Должен быть неотрицательным и меньше размера коллекции".
 – 
Aya Ahmed
8 Ноя 2014 в 19:49
Эта ошибка означает, что ваш код не инициализировал List. Я изменил код, чтобы добавить элемент в коллекцию.
 – 
Dan Guzman
8 Ноя 2014 в 20:20
Лучше всего/работает комбинация/объединение этого ответа и другого ответа от @marc_s. Для этого ответа: 1) вы должны переместить строку var cmd2 над циклом, поскольку она не меняется, 2) вы должны переместить SqlParameter param = new SqlParameter("@IDS", SqlDbType.Int) за пределы цикла, 3) установить param внутри цикла, 4) скорее всего, не нужно while вокруг rdr2.Read(), и 5) вам нужно закрыть считыватель, так как вы не можете выдать другой ExecuteReader до тех пор, пока текущий закрыт (верно?).
 – 
Solomon Rutzky
8 Ноя 2014 в 20:50