Datareader пропускает первый результат

2

У меня довольно сложный SQL-запрос, который вытаскивает различные типы продуктов из базы данных на основе идентификатора клиента. Он вытягивает три разных типа продуктов, идентифицируемых по их уникальным диапазонам номеров идентификаторов (т.е. Идентификаторы 1000-1999 являются одним типом продукта, 2000-2999 - это еще один, а 3000-3999 - еще один).

SELECT b.fldMachineName, m2.fldRotaryPressName, mids.fldMachine_ID
FROM dbo.tblCustomerGeneralInfo c
LEFT JOIN dbo.tblMachine_IDs mids ON c.fldCustomer_ID = mids.fldCustomer_ID
LEFT JOIN dbo.tblBobstFlatDieSpecs b ON mids.fldMachine_ID = b.fldMachine_ID
LEFT JOIN dbo.tblDieInfo m1 ON mids.fldMachine_ID = m1.fldMachine_ID
LEFT JOIN dbo.tblRotaryDieSpecs sm ON m1.fldMachine_ID = sm.fldMachine_ID
LEFT JOIN dbo.tblRotaryPresses m2 ON sm.fldRotaryPress_ID = m2.fldRotaryPress_ID
WHERE c.fldCustomer_ID = '20'
ORDER BY fldRotaryPressName

c.fldCustomer_ID - единственная часть пользовательского ввода, которая мне нужна, и когда я запускаю этот запрос к базе данных в SQL Server Management Studio Express, она работает нормально. Однако, когда я переношу это в оператор using в веб-части, которую я пишу в С# для SharePoint, он не возвращает первую строку, которую он должен, вместо этого возвращает нулевое значение. Например, если в SSMS я получаю три результата (скажем, "1001", "2008" и 3045), тогда мой datareader вернет только два результата с нулевым значением для первого (т.е. "Null", "2008", 'и' 3045 '). Вот мой код в С#:

            con.Open();
            using (SqlCommand cmd = new SqlCommand("SELECT b.fldMachineName, m2.fldRotaryPressName, mids.fldMachine_ID " +
                                                   "FROM dbo.tblCustomerGeneralInfo c " +
                                                   "LEFT JOIN dbo.tblMachine_IDs mids ON c.fldCustomer_ID = mids.fldCustomer_ID " +
                                                   "LEFT JOIN dbo.tblBobstFlatDieSpecs b ON mids.fldMachine_ID = b.fldMachine_ID " +
                                                   "LEFT JOIN dbo.tblDieInfo m1 ON mids.fldMachine_ID = m1.fldMachine_ID " +
                                                   "LEFT JOIN dbo.tblRotaryDieSpecs sm ON m1.fldMachine_ID = sm.fldMachine_ID " +
                                                   "LEFT JOIN dbo.tblRotaryPresses m2 ON sm.fldRotaryPress_ID = m2.fldRotaryPress_ID " +
                                                   "WHERE c.fldCustomer_ID = @CustomerID " +
                                                   "ORDER BY fldRotaryPressName", con))
            {
                cmd.Parameters.Add("@CustomerID", SqlDbType.VarChar, 4).Value = customers.SelectedValue.ToString();

Наш профайлер SQL показывает тот же запрос, который передается независимо от того, выполняется ли он через SSMS или из веб-части, за исключением того, что литерал используется в сравнении с параметром. Кроме того, если я изменю параметр на литерал, я получаю тот же результат. Есть ли несоответствие в том, что С# обрабатывает SQL-запросы в отличие от SSMS или я каким-то образом реализовал его неправильно?

Вот код для извлечения данных из читателя в раскрывающийся список, для полноты:

                    dr.read();
                    while (dr.Read())
                    {
                        try
                        {
                            string itemValue = Convert.ToString(dr["fldMachine_ID"]);
                            string flatName = Convert.ToString(dr["fldMachineName"]);
                            if (!string.IsNullOrEmpty(flatName))
                            {
                                items.Add(flatName, itemValue);
                            }
                            string rotaryName = Convert.ToString(dr["fldRotaryPressName"]);
                            if (!string.IsNullOrEmpty(rotaryName))
                            {
                                items.Add(rotaryName, itemValue);
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString());
                        }
                    }

                        // Bind list to ddl.
                        machines.DataSource = items;
                        machines.DataValueField = "Value";
                        machines.DataTextField = "Key";
                        machines.DataBind();

                        machines.Enabled = true;
                    }

Я полностью в тупике, и я очень ценю любую помощь, которую я могу получить.

  • 0
    Вы проверили, как выглядит ваш запрос в SQL Profiler?
  • 0
    Запустите запрос, используя литерал «11» один раз, без параметров команды, что это возвращает?
Показать ещё 2 комментария
Теги:
sql-server
sharepoint
web-parts
datareader

3 ответа

2
Лучший ответ

Обновление

Выяснилось, что проблема была вызвана дополнительным вызовом dr.Read() перед циклом. См. Комментарии.

Обновление

Глядя на код, кажется, что привязка данных не в том месте - может быть, что-то вроде этого? Кроме того, я изменил его, чтобы показать нулевые элементы... возможно, это вызовет логическую проблему.

while (dr.Read())
{
    try
    {
      string itemValue = dr["fldMachine_ID"].ToString();
      string flatName =  dr["fldMachineName"].ToString();
      if (string.IsNullOrEmpty(flatName)) flatName = "!NULL!";
      if (string.IsNullOrEmpty(itemValue)) itemValue = "!NULL!";
      items.Add(flatName, itemValue);

      string rotaryName = dr["fldRotaryPressName"].ToString();
      if (string.IsNullOrEmpty(rotaryName)) rotaryName= "!NULL!";
      items.Add(rotaryName, itemValue);
    }
    catch (Exception ex)
    {
      MessageBox.Show(ex.ToString());
    }

}
// Bind list to ddl.
machines.DataSource = items;
machines.DataValueField = "Value";
machines.DataTextField = "Key";
machines.DataBind();

machines.Enabled = true;

старый

Может быть, это что-то глупое как customers.SelectedValue.ToString().Trim()?

Вы можете запустить профилировщик и посмотреть ТОЛЬКО SQL, который выполняется сервером... затем запустите это в SSMS, чтобы узнать, все ли у вас разные результаты.

  • 0
    Я не вижу ничего подобного, хотя, полагаю, это не значит, что его там нет. При отладке я подключился к процессу SharePoint и прошел проверку при проверке своих значений, и он, похоже, просто передает параметр ID.
  • 0
    Кроме того, я должен упомянуть, что я также пытался скопировать SQL-запрос, отправленный веб-частью из профилировщика, и вставить его в SSMS. У меня был такой же результат.
Показать ещё 22 комментария
2

ваш пример кода показывает, что вы дважды вызываете Read on DataReader в начале, что заставит читателя пропустить первую строку. Вам нужен только вызов чтения во время цикла while.

  dr.read();  // unnecessary read call
  while (dr.Read())
  { }
  • 0
    Примечание: код некоторое время выглядел по-другому, прежде чем он нашел проблему и поместил read () в пример кода.
0

Вы выполняете привязку данных внутри цикла чтения. Действительно, вы должны привязываться к перечислимому после его заполнения.

Также посмотрите на метод command.AddWithValue().

  • 0
    AddWithValue (), вероятно, потерпит неудачу. Он хочет, чтобы числа представлялись в виде строк, а AWV следует преобразовать в число. (Конечно, customerID должен быть представлен как int в БД, но это другая история ...)
  • 0
    Моя ошибка там. Хоган указал на это в первый раз, и я все исправил. Я просто скопировал этот фрагмент в неправильное место, когда обновил свой код. Я посмотрел на AddWithValue, но да, я не вижу его работоспособным, поскольку все, с чем я имею дело, это строки.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню