0

準備されたステートメントを使用してアクセスデータベースに情報を (行ごとに) 書き込む c# のコードがいくつかあります。OleDb と TransactionLevel.ReadUncommitted を使用しています。コミットする前にデータを確認する必要がある場合があるためです。

問題は、7 つの異なるテーブルのうちの 1 つで、データベースからレコードを取得する順序が、入れた順序と同じではないことです。これは、使用しようとする 4 回ごとに約 1 回発生するため、実際にはデバッグできないようです。

編集 ここで順序付けが重要な理由は、そこに既に存在するデータと一致する Excel シートにテーブルをダンプしているためです。並べ替えは多少進むかもしれませんが、シート上のデータと一致するように並べ替えることができなかった動き (つまり、N-NW) によって並べ替えられた列があります。

私はそれが準備されたステートメントの挿入コマンドの競合状態であることに傾いています(つまり、一度に処理するにはアクセスするには多すぎるため、混乱します)。

誰もこれについて何か考えがありますか?以下は、私がやっていることのいくつかのスニペットです:

protected override void PopulateTmpTable()
  {
    OleDbCommand objComm = null;
    try
    {
      objComm = new OleDbCommand("", mDbconn);
      ...
      //Begin SQL Transaction
      mTr = mDbconn.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted);
      objComm.Transaction = mTr;
      //Start Populating Temp Table
      for (int i = 1; i <= mNrows; i++)
      {
        ...
        ProcessNode(objComm, node, approaches);
        ProcessNodeSummary(objComm, node);
      }
      ProcessSummary(objComm);
    }
    catch (Exception e) { }
    finally
    {
      if (mTr != null) mTr.Commit();
      if (objComm != null) objComm.Dispose();
    }
  }  //End Method PopulateTmpTable

  private void ProcessNode(OleDbCommand objComm, string node, List<string> approaches)
  {
    try
    {
      ...
      OleDbCommand objComm2 = new OleDbCommand("", mDbconn, mTr);
      for (int k = 0; k < MaxLegs; k++)
      {
        ...
            total = ProcessIterations(objComm, node, turning[m], m);
          }
          objComm.ExecuteNonQuery();
        }  //End if
      }  //End for
    }
    catch { }
  }  //End Method ProcessNode

private List<double> ProcessIterations(OleDbCommand objComm, string node, string turn, int m)
  {
    try
    {
      OleDbCommand objComm2 = new OleDbCommand("", mDbconn, mTr);
      OleDbDataReader objRead;
      objComm.Parameters["parameter"].Value = //Stuff (x2)
        for (int j = 0; j < mIterations; j++)
        {
          ...
          objComm2.CommandText = "SELECT ROUND(AVG(Delay),1), COUNT(VehNo) FROM [TABLE] WHERE NodeNo=" + node + " AND Movement='" + turn + "' AND Iteration=" + mIterationValue[j] + mFilter[1];
          objRead = objComm2.ExecuteReader();
          objRead.Read();
          try
          {
              objComm.Parameters["more parameters"].Value = objRead[0];
              ...
          }
          catch { }
          objRead.Close();
        }//End for
        ...
        objComm.ExecuteNonQuery();
        objComm2.CommandText = "UPDATE " + mTmptable + " SET ave=" + avg + ",minimum=" + mMini[m] + ",maximum=" + mMaxi[m] + ",dev=" + stDev + " WHERE node='" + node + "' AND movement = '" + temp + "';";
        objComm2.ExecuteNonQuery();
      }
    }
    catch{}
    return mTotal;
  }  //End Function ProcessIterations
4

2 に答える 2

0

PopulateTmpTable() メソッドでは、エラーが発生した場合でもトランザクションをコミットしています。それはあなたが意図したものですか?

ProcessNode() では、コマンド オブジェクトを渡し、新しいオブジェクトを作成してから、渡されたオブジェクトを使用しますか?

于 2009-01-17T00:56:34.397 に答える
0

Jet では、テーブルのクラスター化されたインデックス (物理的な順序付け) は PRIMARY KEY によって決定されます。PK がない場合は、エンジンによって (ランダムに?) 選択された別のキーによって決定されます。ただし、物理的な順序付けは、データベース ファイル (.mdb、.mde、.accdb) が圧縮されている場合にのみ発生します。圧縮後 (または最初の圧縮前) に挿入された行は、日付/時刻順に挿入されます。現在、Jet の DATETIME データ型でサポートされている最小の時間粒度は 1 秒ですが、内部では値が double float として格納されているため、粒度が目的に十分ではないかどうか疑問に思っています。しかし、古いエンジンのドキュメント化されていない機能に依存する必要はありません...?

行を挿入する順序がわかっている場合は、これをデータベースでモデル化します。たとえば、INTEGER 列を使用して、アプリが値の提供を担当するシーケンス番号を格納します。念のため、列にも UNIQUE 制約を設定します。次に、クエリでシーケンス列を単純に ORDER BY します。

于 2009-01-20T09:12:30.970 に答える