好的,我正在运行此代码,将大量数据从普及数据库移动到访问数据库
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:
如您所见,调试器已经进入阅读器
答案 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
了