Datareader пропускает первый результат - PullRequest
2 голосов
/ 20 января 2010

У меня довольно сложный запрос 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, он работает нормально. Тем не менее, когда я заключаю это в оператор использования в веб-части, которую я пишу на C # для SharePoint, он не возвращает первую строку, которую должен, вместо этого возвращает нулевое значение. Например, если в SSMS я получу три результата (скажем, «1001», «2008» и «3045»), тогда мой datareader вернет только два результата с нулевым значением для первого (т. Е. «Null», «2008»). , 'и' 3045 '). Вот мой код в C #:

            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 или из веб-части, за исключением того, что литерал используется вместо параметра. Кроме того, если я изменю параметр на литерал, у меня будет тот же результат. Есть ли расхождения в способе, которым C # обрабатывает запросы 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;
                    }

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

Ответы [ 3 ]

2 голосов
/ 29 января 2010

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

  dr.read();  // unnecessary read call
  while (dr.Read())
  { }
2 голосов
/ 20 января 2010

обновление

Оказалось, что проблема заключалась в дополнительном вызове 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 голосов
/ 28 января 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...