为什么运行第二个阅读器与第一个阅读器read()运行得更快,然后运行它自己的读者阅读?

时间:2012-03-26 15:22:59

标签: c# sql ms-access oledb

好的,我正在运行此代码,将大量数据从普及数据库移动到访问数据库

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,如果它正在为第一个执行读取操作,那么它不应该在标题表的末尾完成然后停止吗?那么为什么那里的所有数据呢?

无论哪种方式,此代码的运行时间相对较慢,是否有人有任何改进我的代码的建议?

编辑:只是为了表明第二个读者没有返回false: Debugger

如您所见,调试器已经进入阅读器

3 个答案:

答案 0 :(得分:4)

您确定在第二次调用myreader时获得了正确的数据吗? 有些东西看起来不正确:您在循环myreader时应该从第一个SELECT语句获取数据,但内部代码引用myreader1

所以这里奇怪的不是第二次迭代应该比第一次迭代更快:第二次迭代会返回你期望的数据。
所以问题是:你确定在第二个循环中:

  • 您获得了期望从第二个SELECT语句中获得的所有记录的预期迭代次数,例如5000(与第一个语句中的记录数相反,比如说1000)。 / p>

  • 您实际上是在第二个SELECT语句中获取每条记录的数据,而不是每次都获得相同的顶级记录。

关于问题的第二部分,如何提高数据传输的速度,我建议如下:

  • 通过执行单个INSERT语句添加数据的速度会很慢 对于一些非常快速的替代方案,请看一下这个问题:
    Writing large number of records (bulk insert) to Access in .NET/C#

  • 如果您在Access数据库上做了大量工作,请保持连接永久打开,而不是打开/关闭它。由于这会对性能产生重大影响,请参阅Where is the OLE DB connection pooling? 我通常创建一个我称为Dummy的表,其中包含一条记录(无关紧要),然后在该表上打开一个数据阅读器,直到关闭应用程序为止。这可以确保每次对数据库执行某些操作时,数据库锁定文件都会保留在原位并且不会创建/删除。如果你在数据库上做了很多操作,你会对它对性能的影响感到惊讶。

答案 1 :(得分:1)

你能告诉我们最慢的线路吗?

尝试使用块来处理IDisposable对象,例如DB Connections。通过这种方式,您可以在出现异常时保持安全。而且你不需要明确地调用Close()。

for循环有很多字符串添加。请尝试使用StringBuilder。

答案 2 :(得分: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();
        }

此代码冗余有两个原因

  • 我应该在阅读器中添加数据库,而不是创建一个for循环,该循环遍历我创建的列表,而不是用于其他任何内容

  • 我正在清空表并用相同的数据+额外的数据重新填充它,当我应该检查我插入的是否已经存在然后只插入当前不存在的行

我已使用此

替换了该代码
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#

中建议的那样使用DAO

因为我已经在使用system.data.OleDb