【问题标题】:Datareader skips first resultDatareader 跳过第一个结果
【发布时间】:2011-01-07 00:17:50
【问题描述】:

我有一个相当复杂的 SQL 查询,它根据客户 ID 从数据库中提取不同类型的产品。它提取三种不同类型的产品,由它们的唯一标识符编号范围标识(即,ID 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# for SharePoint 编写的 Web 部件中的 using 语句中包装它时,它不会返回它应该返回的第一行,而是返回一个空值。例如,如果在 SSMS 中我得到三个结果(例如,'1001'、'2008' 和 3045'),那么我的数据读取器将只返回两个结果,第一个结果为空值(即,'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();

无论是通过 SSMS 还是从 Web 部件完成,我们的 SQL 分析器都会显示正在传递的相同查询,但使用的文字与参数不同。另外,如果我将参数更改为文字,我会得到相同的结果。与 SSMS 相比,C# 处理 SQL 查询的方式是否存在差异,或者我是否以某种方式错误地实现了它?

为了完整起见,这里是从阅读器中提取数据到下拉列表中的代码:

                    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;
                    }

我完全被难住了,非常感谢我能得到的任何帮助。

【问题讨论】:

  • 您检查过您的查询在 SQL Profiler 中的样子吗?
  • 使用文字 '11' 运行一次查询,没有命令参数,返回什么?
  • 您是否在代码中使用 11 的 CustomerID 进行测试?
  • 我通过我们的分析器查看了从两端运行的查询,除了参数与文字之外,没有发现任何差异。我尝试更改 Web 部件以将 ID 作为文字发送,然后直接将文字分配给参数,两种方式都存在同样的问题。我难住了。我确信此时会有什么东西跳出来。

标签: c# sql-server sharepoint datareader web-parts


【解决方案1】:

更新

原来问题是循环之前的一个额外的 dr.Read() 调用。见 cmets。

更新

查看代码,似乎数据绑定在错误的位置——可能是这样的?另外,我将其更改为显示空项目...也许这会暴露一个逻辑问题。

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 中运行它以查看是否仍会得到不同的结果。

【讨论】:

  • 我没有看到类似的东西,尽管我想这并不意味着它不存在。在调试中,我已附加到 SharePoint 进程并在检查我的值时逐步执行,它似乎可以很好地传递 ID 参数。
  • 另外,我应该提一下,我还尝试复制 Web 部件从分析器发出的 SQL 并将其粘贴到 SSMS 中。我得到了同样的结果。
  • 我很清楚,当您将在 Profiler 中看到的代码并在 Enterprise Manager 中运行时,您会得到预期的结果吗?
  • 我现在实际上没有 MS Profiler ...我们的服务器软件仅对网络管理员可用,所以我正在等待与某人交谈以在我的机器上安装它。但是,我确实使用了 Arj Lab 的开源分析器来获得我之前提到的结果。我现在要试试你上面的代码,看看我是否能找到逻辑中的一些错误。感谢您的帮助!
  • 好的。空值似乎是问题的一部分。我在上面交换了您的代码,并使用 Web 部件对数据库运行了一些查询。我现在收到几个“!NULL!”对于给我带来问题的客户,我的价值观与我的结果混合在一起。我现在正在研究逻辑,但我很乐意接受您的更多输入!
【解决方案2】:

您的代码示例显示您在开始时两次在 DataReader 上调用 Read,这将导致阅读器跳过第一行。您应该只需要 while 循环中的 read 调用。

  dr.read();  // unnecessary read call
  while (dr.Read())
  { }

【讨论】:

  • 附注:在他发现问题并将 read() 放入代码示例之前,代码看起来有一段时间不同。
【解决方案3】:

您正在读取循环内进行数据绑定。确实,您应该在填充后绑定到可枚举。

另外,看看command.AddWithValue() 方法。

【讨论】:

  • AddWithValue() 可能会失败。他希望数字表示为字符串,AWV 应该转换为数字。 (当然,customerID 应该在数据库中表示为 int,但那是另一回事了……)
  • 我错了。霍根第一次指出了这一点,我确实修复了它。当我更新我的代码时,我只是将该块复制到错误的位置。我看过 AddWithValue,但是,我认为它不起作用,因为我处理的所有内容都是字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多