2012-03-26 37 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