2012-03-26 32 views
3

好了,所以,我目前正在運行此代碼從一種普遍的數據庫移到一組數據到Access數據庫爲什麼第一個閱讀器運行第二個閱讀器讀取()運行得更快,然後在自己的閱讀器上運行呢?

public List<HBPData> LoadData() 
    { 

     loadConnect(); //<-- get's the Pervasive/Access string from a text file 
     List<HBPData> listofhbpdata1 = new List<HBPData>(); 
     List<HBPData> listofhbpdata2 = new List<HBPData>(); 

      PsqlConnection myConnection = new PsqlConnection(); 
      myConnection.ConnectionString = PervasiveString; 
      myConnection.Open(); 
      PsqlCommand myCommand = new PsqlCommand("Select NUMBER, CUST_NAME, PO_NO, REQD_DATE, PO_NO, CUST_PO_NO, ORD_DATE, STATUS FROM SALES_ORDER_HEADER WHERE ORD_DATE > 20120220 Order By ORD_DATE desc", myConnection); 
      PsqlDataReader myreader = null; 
      myreader = myCommand.ExecuteReader(); 

      while (myreader.Read()) 
      { 
       HBPData DataEntity = new HBPData(); 
       DataEntity.NUMBER = (myreader["NUMBER"].ToString()); 
       DataEntity.CUST_NO = (myreader["CUST_NAME"].ToString()).Replace("'",""); 
       DataEntity.PO_NO = (myreader["PO_NO"].ToString()); 
       DataEntity.RequiredDateTime = (myreader["REQD_DATE"].ToString()); 
       DataEntity.Tag = (myreader["PO_NO"].ToString()); 
       DataEntity.Shape = (myreader["CUST_PO_NO"].ToString()); 
       DataEntity.ExpectedCompletion = myreader["ORD_DATE"].ToString().Substring(0, 4) + "/" + myreader["ORD_DATE"].ToString().Substring(4, 2) + "/" + myreader["ORD_DATE"].ToString().Substring(6, 2); 
       DataEntity.MostRecentStatus = (myreader["STATUS"].ToString()); 
       listofhbpdata1.Add(DataEntity); 
      } 

      PsqlCommand myCommand1 = new PsqlCommand("Select NUMBER, RECNO, CODE, ORDD_DESCRIPTION, BVORDQTY FROM SALES_ORDER_DETAIL WHERE BVRVADDDATE > 20120220 AND (PROD_CODE = \'MET\' OR PROD_CODE = \'MDT\') Order By NUMBER desc", myConnection); 
      PsqlDataReader myreader1 = null; 
      myreader1 = myCommand1.ExecuteReader(); 

      while (myreader.Read()) 
      { 
       HBPData DataEntity = new HBPData(); 
       DataEntity.NUMBER = (myreader1["NUMBER"].ToString()); 
       DataEntity.RECNO = (myreader1["RECNO"].ToString()); 
       DataEntity.CODE = (myreader1["CODE"].ToString()); 
       DataEntity.DESCRIPTION = (myreader1["ORDD_DESCRIPTION"].ToString()); 
       DataEntity.Quantity = (myreader1["BVORDQTY"].ToString()); 
       listofhbpdata2.Add(DataEntity); 
      } 

      myConnection.Close(); 
      myreader1.Close(); 
      myreader.Close(); 






      System.Data.OleDb.OleDbConnection myAccessConnection = new System.Data.OleDb.OleDbConnection(); 

      myAccessConnection.ConnectionString = AccessString; 
      myAccessConnection.Open(); 
      System.Data.OleDb.OleDbCommand myAccessCommand3 = new System.Data.OleDb.OleDbCommand("delete from AllOrders", myAccessConnection); 
      myAccessCommand3.ExecuteNonQuery(); 

      for (int i = 0; i < listofhbpdata2.Count(); ++i) 
      { 
       System.Data.OleDb.OleDbCommand myAccessCommand2 = new System.Data.OleDb.OleDbCommand("" + 
        "Insert into AllOrders VALUES('" + 
         listofhbpdata2[i].NUMBER + "'" + ",'" + listofhbpdata2[i].RECNO.ToString() + "'" + 
        ",'" + listofhbpdata2[i].CODE + "','" + listofhbpdata2[i].DESCRIPTION.Replace("\'", "F") + "'" + 
        ",'" + listofhbpdata2[i].Quantity + "')", myAccessConnection); 
       myAccessCommand2.ExecuteNonQuery(); 
      } 

      myAccessConnection.Close(); 

     return listofhbpdata1; 
    } 

現在,.如果你仔細看,我打錯了第二個閱讀器,它應該閱讀,而(myreader1.read())...我不小心把myreader.read()

把myreader.read()讓我驚訝運行成功... 這是一種什麼樣的自爆...... 我將它改爲「myreader1.read()」 ,代碼的運行時間幾乎是雙倍......, 反正,檢查數據庫,所有的數據在那裏......

所以,使用常識,我覺得很好,它可能只是每次運行第一個閱讀器都會執行兩套代碼,

但那麼如何來所有的數據呢?

Sales_Order_Header中的字段顯着少於Sales_Order_Detail,如果它正在爲第一個讀取器執行讀取操作,是不是應該在標題表的末尾完成,然後停止?那麼爲什麼所有數據都在那裏?

無論哪種方式,這段代碼的運行時間相對較慢,有沒有人有任何改善我的代碼的建議?

編輯:只是爲了表明第二讀卡器未INFACT返回false: Debugger

,你可以看到,調試器已加強了讀者的內部

+0

您是否嘗試過在StackExchange家網站的代碼審查懶得使用DAO? – GregC 2012-03-26 15:29:17

回答

1

我不知道爲什麼,但我想我會寫出一個答案,我自己的問題。

雖然我沒有爲什麼第二個讀者成功運行(而不丟失數據)一個很好的答案,我有使這個代碼的運行速度是不建議

第一關的幾種方法〜

while (myreader.Read()) 
     { 
      HBPData DataEntity = new HBPData(); 
      DataEntity.NUMBER = (myreader1["NUMBER"].ToString()); 
      DataEntity.RECNO = (myreader1["RECNO"].ToString()); 
      DataEntity.CODE = (myreader1["CODE"].ToString()); 
      DataEntity.DESCRIPTION = (myreader1["ORDD_DESCRIPTION"].ToString()); 
      DataEntity.Quantity = (myreader1["BVORDQTY"].ToString()); 
      listofhbpdata2.Add(DataEntity); 
     } 

     myConnection.Close(); 
     myreader1.Close(); 
     myreader.Close(); 






     System.Data.OleDb.OleDbConnection myAccessConnection = new System.Data.OleDb.OleDbConnection(); 

     myAccessConnection.ConnectionString = AccessString; 
     myAccessConnection.Open(); 
     System.Data.OleDb.OleDbCommand myAccessCommand3 = new System.Data.OleDb.OleDbCommand("delete from AllOrders", myAccessConnection); 
     myAccessCommand3.ExecuteNonQuery(); 

     for (int i = 0; i < listofhbpdata2.Count(); ++i) 
     { 
      System.Data.OleDb.OleDbCommand myAccessCommand2 = new System.Data.OleDb.OleDbCommand("" + 
       "Insert into AllOrders VALUES('" + 
        listofhbpdata2[i].NUMBER + "'" + ",'" + listofhbpdata2[i].RECNO.ToString() + "'" + 
       ",'" + listofhbpdata2[i].CODE + "','" + listofhbpdata2[i].DESCRIPTION.Replace("\'", "F") + "'" + 
       ",'" + listofhbpdata2[i].Quantity + "')", myAccessConnection); 
      myAccessCommand2.ExecuteNonQuery(); 
     } 

此代碼是多餘的,原因有二

  • 我應該添加到數據庫內的讀者,因爲反對創建一個循環,通過我創建的列表,而不是用於其他任何東西

  • 我正在清空表並重新填充相同的數據+額外的數據,當我要檢查,如果什麼我將已經存在,然後將只有目前不存在

我更換了代碼行,這個

while (myreader1.Read()) 
        { 
    System.Data.OleDb.OleDbCommand myAccessCommand2 = new System.Data.OleDb.OleDbCommand(
    "INSERT INTO AllOrders(OrderNumber,RecordNumber,Code, Description, Quantity) " + 
    "SELECT TOP 1 '" + (myreader1["NUMBER"].ToString()) + "'" + ",'" + myreader1["RECNO"].ToString() + "'" + 
    ",'" + (myreader1["CODE"].ToString()) + "','" + (myreader1["ORDD_DESCRIPTION"].ToString()).Replace("\'", "F") + "'" + 
    ",'" + (myreader1["BVORDQTY"].ToString()) + "'" + 
    " from AllOrders " + 
    "WHERE NOT EXISTS(SELECT TOP 1 OrderNumber FROM AllOrders Where OrderNumber = '" + myreader1["NUMBER"].ToString() +"')", myAccessConnection); 
         myAccessCommand2.ExecuteNonQuery(); 

        } 

現在

即使運行myreader.read似乎進展得更快,我只是在情況下,它做壞事,我無法找到myreader1取而代之

現在運行得更快。我不喜歡提出在Writing large number of records (bulk insert) to Access in .NET/C#

,因爲我已經在使用system.data.OleDb

1

你能不能給我們運行線路最慢?

嘗試使用塊來處理IDisposable對象,如數據庫連接。這樣,你會在例外情況下安全。你不需要明確調用Close()。

For循環有很多字符串加法。改爲使用StringBuilder。

+0

如果你指的是try catch塊,我以前有一個try catch塊,我將它刪除了,因爲我認爲它會佔用資源,並且不會拋出任何異常 – 2012-03-26 15:34:35

+0

數據庫訪問可能會拋出。由於你不控制SQL引擎代碼(我認爲)。如果拋出,則會泄漏主要資源,如數據庫連接。 – GregC 2012-03-26 15:37:24

+0

噢..運行速度最慢的線是打開普及數據庫連接,我懷疑有什麼我可以做的<。< – 2012-03-26 15:39:40

4

您確定在第二次致電myreader時獲得正確的數據嗎? 有些東西看起來不正確:您循環使用myreader應該從您的第一個SELECT聲明中獲取數據,但您的內部代碼引用myreader1

所以這裏的奇怪的事情並不是第二次迭代應該比第一次迭代更快:它是第二次迭代將您所期望的數據返回給您。
所以,問題是:你肯定在第二循環:

  • 你得到迭代的預期數量爲你從第二SELECT聲明期望的記錄,說5000(而不是在來自第一條語句的記錄數,例如1000)。

  • 您實際上是在第二個SELECT聲明中獲取每條記錄的數據,而不是每次都記錄同一條記錄。通過個人INSERT語句的執行

    • 添加數據將:

    關於你問題的第二部分,如何提高數據傳輸的速度,我想提出以下建議緩慢。
    看一看這個問題,對於一些非常快的替代品:
    Writing large number of records (bulk insert) to Access in .NET/C#

  • 如果你做了很多你的Access數據庫的工作,保持連接永久開放它,而不是打開/關閉它。爲什麼這可能會對性能產生重大影響,請參閱Where is the OLE DB connection pooling?
    我通常會創建一個表,我叫Dummy,在它的單個記錄(不要緊,它是什麼),然後打開該表的數據讀取器,我保持開放,直到我關閉應用程序。這可以確保數據庫鎖定文件保留在原位,並且不會在每次對數據庫執行某些操作時創建/刪除。如果您在數據庫上進行了大量操作,您會驚訝於它對性能的影響。

+0

所有的數據正在傳輸我已經徹底檢查,我不能留下一個連接打開數據庫,因爲A)它在文件服務器上工作(這會減慢其他人)B)其他程序/應用程序使用相同的數據庫和如果我將連接打開,他們將獲得自己的速度問題,並說你的批量插入?也許我會給它一個去:P – 2012-03-30 19:54:54

+0

我拼寫檢查D: – 2012-03-31 01:45:21

+0

保持一個鏈接打開到Access數據庫不會影響其他用戶連接到它。 Access是一個文件數據庫。如果沒有其他連接打開,則每次打開/關閉連接時,ACE引擎都必須檢查鎖定文件並創建/刪除它,這耗費大量時間。如果因爲您保持鏈接處於打開狀態而已經創建了鎖定文件,則隨後的打開/關閉將非常快。服務器上沒有資源被使用,你可以有100個人連接到虛擬表。它不會以任何方式影響性能。最後一個關閉虛擬表的人也將刪除鎖文件。 – 2012-03-31 02:25:04