2

顧客 ID に基づいてデータベースからさまざまな種類の製品を取得する、かなり複雑な SQL クエリがあります。一意の ID 番号の範囲 (つまり、ID 1000 ~ 1999 は製品の 1 つのタイプ、2000 ~ 2999 は別のタイプ、3000 ~ 3999 はさらに別のタイプ) によって識別される 3 つの異なるタイプの製品をプルします。

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 でデータベースに対してこのクエリを実行すると、問題なく実行されます。ただし、SharePoint 用に C# で記述している Web パーツの using ステートメントでこれをラップすると、本来あるべき最初の行が返されず、null 値が返されます。たとえば、SSMS で 3 つの結果 ('1001'、'2008'、および 3045' など) を取得した場合、データリーダーは 2 つの結果のみを返し、最初の値は null 値 (つまり、'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 を介して行われたか Web パーツから行われたかに関係なく、同じクエリが渡されることを示しています。また、パラメーターをリテラルに変更すると、同じ結果になります。C# が SSMS とは対照的に 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;
                    }

私は完全に困惑しており、私が得ることができるどんな助けにも本当に感謝しています.

4

3 に答える 3

2

コードサンプルは、最初にDataReaderでReadを2回呼び出すことを示しています。これにより、リーダーは最初の行をスキップします。whileループでの読み取り呼び出しのみが必要です。

  dr.read();  // unnecessary read call
  while (dr.Read())
  { }
于 2010-01-29T14:16:54.877 に答える
2

アップデート

問題は、ループの前に余分な dr.Read() 呼び出しであることが判明しました。コメントを参照してください。

アップデート

コードを見ると、データバインドが間違った場所にあるようです - おそらくこのようなものでしょうか? また、null アイテムを表示するように変更しました...これにより、ロジックの問題が発生する可能性があります。

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でそれを実行して、まだ異なる結果が得られるかどうかを確認します。

于 2010-01-19T21:08:53.733 に答える
0

読み取りループ内でデータバインドを実行しています。実際には、データが入力された後に列挙可能にバインドする必要があります。

また、command.AddWithValue()方法を見てください。

于 2010-01-28T16:35:17.470 に答える