我从我的SQL服务器获取数据并将它们放入表中,但由于存在数千行数据,因此该过程需要很长时间。如何更快地完成此过程?
我目前正在使用foreach
循环向表中添加新行,即使处理20行数据,也需要大约2到3秒。以下是我的代码,我该如何改进? (代码有点长,对不起,但我想展示整个事情,以便讲述整个故事)
/*
* A class that return bestbuy export table
*/
class BestbuyExportTable
{
// field for the main table
private DataTable mainTable;
// field for database connection
SqlConnection connection;
/* constructor that initialize fields */
public BestbuyExportTable()
{
mainTable = new DataTable();
connection = new SqlConnection(Properties.Settings.Default.ConnectionString);
}
/* the real thing -> return the table !!! */
public DataTable getTable()
{
// reset table just in case
mainTable.Reset();
// add column to table
addColumn(mainTable, "SKU"); // 1
addColumn(mainTable, "DEPARTMENT"); // 2
addColumn(mainTable, "SHORT DESCRIPTION"); // 3
addColumn(mainTable, "LONG DESCRIPTION"); // 4
addColumn(mainTable, "UPC (PRIMARY)"); // 4
addColumn(mainTable, "UPC (ADDITIONAL)"); // 5
addColumn(mainTable, "BRAND NAME"); // 6
addColumn(mainTable, "MODEL NO"); // 7
addColumn(mainTable, "MANUFACTURER"); // 8
addColumn(mainTable, "SUPPLIER"); // 9
addColumn(mainTable, "VENDOR PART NO"); // 10
addColumn(mainTable, "UNIT COST"); // 11
addColumn(mainTable, "RETAIL PRICE"); // 12
addColumn(mainTable, "DIMENSION (CM) WIDTH (WITH BOX)"); // 13
addColumn(mainTable, "DIMENSION (CM) HEIGHT (WITH BOX)"); // 14
addColumn(mainTable, "DIMENSION (CM) LENGTH/DEPTH (WITH BOX)"); // 15
addColumn(mainTable, "DIMENSION (KG) WEIGHT (WITH BOX)"); // 16
addColumn(mainTable, "DIMENSION (CM) WIDTH (NO BOX)"); // 17
addColumn(mainTable, "DIMENSION (CM) HEIGHT (NO BOX)"); // 18
addColumn(mainTable, "DIMENSION (CM) LENGTH/DEPTH (NO BOX)"); // 19
addColumn(mainTable, "DIMENSION (KG) WEIGHT (NO BOX)"); // 20
addColumn(mainTable, "FRENCH COMPLIANT"); // 21
addColumn(mainTable, "ENERGY STAR"); // 22
addColumn(mainTable, "REFURBISHED"); // 23
addColumn(mainTable, "SOFTWARE PLATFORM"); // 24
addColumn(mainTable, "STREET DATE"); // 25
addColumn(mainTable, "SERIAL NO REQUIRED"); // 26
addColumn(mainTable, "SERIALIZED FORMAT"); // 27
addColumn(mainTable, "SUPPORT MANUFACTURER WARRANTY"); // 28
addColumn(mainTable, "SERVICE UNDER MNF WARRANTY"); // 29
addColumn(mainTable, "SERVICE OUTSIDE MNF WARRANTY"); // 30
addColumn(mainTable, "SUPPLIER CONTACT"); // 31
addColumn(mainTable, "ALWAYS RTV"); // 32
addColumn(mainTable, "RETURN TO VENDOR DEFECTIVE DATE"); // 33
addColumn(mainTable, "RETURN TO VENDOR OPEN BOX DAYS"); // 34
addColumn(mainTable, "PRODUCT WARRANTY DAYS"); // 35
addColumn(mainTable, "PRODUCT WARRANTY COVERAGE"); // 36
addColumn(mainTable, "EXTENDED PARTS WARRANTY"); // 37
addColumn(mainTable, "RETURN RESTRICTIONS"); // 38
addColumn(mainTable, "EMBARGO DATE"); // 39
addColumn(mainTable, "EXPIRATION DATE/LOT NUMBER"); // 40
addColumn(mainTable, "SHELF LIFE"); // 41
addColumn(mainTable, "DATA FLAG"); // 42
addColumn(mainTable, "LESS THAN TRUCKLOAD"); // 43
addColumn(mainTable, "SKU_BESTBUY_CA"); // 44
// local field for inserting data to table
DataRow row;
AltText alt = new AltText(); // this is just a class that get the alt text of a product
string[] skuList = getSKU();
// add data to each row
foreach (string sku in skuList)
{
string[] list = getData(sku);
row = mainTable.NewRow();
row[0] = sku; // sku
row[1] = "104"; // department
row[2] = alt.getAlt(sku); // short description
row[3] = list[0]; // long description
row[4] = list[9]; // upc code primary
row[5] = list[10]; // upc code additional
row[6] = "Ashlin®"; // brand name
row[7] = list[1]; // model no
row[8] = "Ashlin®"; // manufacturer
row[9] = "234326"; // supplier
row[10] = sku; // vendor
row[11] = (Math.Round((Convert.ToDouble(list[11]) * 0.5775), 2)).ToString(); // unit cost
row[12] = (Math.Ceiling((Convert.ToDouble(list[11]) * 1.06)) - 0.01).ToString(); // retail price
row[13] = list[2]; // dimension width (with box)
row[14] = list[3]; // dimension height (with box)
row[15] = list[4]; // dimension length (with box)
row[16] = (Convert.ToDouble(list[5]) / 1000).ToString(); // dimension weight (with box)
row[17] = list[2]; // dimension width (no box)
row[18] = list[3]; // dimension height (no box)
row[19] = list[6]; // dimension length (no box)
row[20] = list[7]; // dimension weight (no box)
row[21] = 'Y'; // french compliant
row[23] = 'N'; // refurbished
row[24] = 'N'; // software platform
row[26] = 'N'; // serial no required
row[28] = 'N'; // support manufacturer warranty
row[29] = 'Y'; // service under mnf warranty
row[30] = 'N'; // service outside mnf warranty
row[31] = 8884274546; // supplier contact
row[32] = 'N'; // always rtv
row[33] = 0; // return to vendor defective date
row[34] = 0; // return to vendor open box days
row[35] = 365; // peoduct warranty days
row[44] = list[8]; // sku bestbuy ca
mainTable.Rows.Add(row);
}
return mainTable;
}
/* method that add new column to table */
private void addColumn(DataTable table, string name)
{
// set up column
DataColumn column = new DataColumn();
column.ColumnName = name;
// add column to table
table.Columns.Add(column);
}
/* a method that get all the sku that is active and sell on bestbuy*/
private string[] getSKU()
{
// local field for storing data
List<string> skuList = new List<string>();
// connect to database and grab data
SqlCommand command = new SqlCommand("SELECT SKU_Ashlin FROM master_SKU_Attributes WHERE SKU_BESTBUY_CA is NOT NULL AND Active = \'TRUE\' ORDER BY SKU_Ashlin;", connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
skuList.Add(reader.GetString(0));
}
connection.Close();
return skuList.ToArray();
}
/* method that get the data from given sku */
private string[] getData(string sku)
{
// local field for storing data
List<string> list = new List<string>();
DataTable table = new DataTable();
// get the design code from sku
string design = sku.Substring(0, sku.IndexOf('-'));
// grab data from design
// [0] for long description, [1] for model no, [2] for diemsion width (with box), [3] for dimension height (with box), [4] for dimension legth (with box), [5] for dimension weight (with box), [6] for dimension length (no box), [7] for dimension weight(no box)
// and (no box) and (no box)
SqlDataAdapter adapter = new SqlDataAdapter("SELECT Extended_Description, Design_Service_Fashion_Name_BESTBUY_CA, Width_cm, Height_cm, Shippable_Depth_cm, Shippable_Weight_grams, Depth_cm, Weight_grams FROM master_Design_Attributes WHERE Design_Service_Code = \'" + design + "\';", connection);
connection.Open();
adapter.Fill(table);
for (int i = 0; i <= 7; i++)
{
list.Add(table.Rows[0][i].ToString());
}
table.Reset();
// [8] for SKU_BESTBUY_CA, [9] for upc code primary, [10] for upc code additional, [11] for unit cost and retail price
adapter = new SqlDataAdapter("SELECT SKU_BESTBUY_CA, UPC_Code_9, UPC_Code_10, Base_Price FROM master_SKU_Attributes WHERE SKU_Ashlin = \'" + sku + "\';", connection);
adapter.Fill(table);
for (int i = 0; i <= 3; i++)
{
list.Add(table.Rows[0][i].ToString());
}
connection.Close();
return list.ToArray();
}
}
}
答案 0 :(得分:2)
将using
用于IDisposable
的课程
使用Reader
,Adapter
并始终使用SQLConnection
一个
using(var reader = command.ExecuteReader();)
{
while (reader.Read())
{
skuList.Add(reader.GetString(0));
}
}
connection.Dispose();
两个
using(var adapter = new SqlDataAdapter("SELECT Extended_Description, Design_Service_Fashion_Name_BESTBUY_CA, Width_cm, Height_cm, Shippable_Depth_cm, Shippable_Weight_grams, Depth_cm, Weight_grams FROM master_Design_Attributes WHERE Design_Service_Code = \'" + design + "\';", connection))
{
connection.Open();
adapter.Fill(table);
for (int i = 0; i <= 7; i++)
{
list.Add(table.Rows[0][i].ToString());
}
table.Reset();
adapter = new SqlDataAdapter("SELECT SKU_BESTBUY_CA, UPC_Code_9, UPC_Code_10, Base_Price FROM master_SKU_Attributes WHERE SKU_Ashlin = \'" + sku + "\';", connection);
adapter.Fill(table);
for (int i = 0; i <= 3; i++)
{
list.Add(table.Rows[0][i].ToString());
}
}
connection.Dispose();
答案 1 :(得分:1)
在将一堆数据加载到DataTable之前,请调用BeginLoadData https://msdn.microsoft.com/en-us/library/system.data.datatable.beginloaddata(v=vs.110).aspx。它将关闭一些内部约束和通知。加载完数据后,请调用EndLoadData。
答案 2 :(得分:0)
我解决了问题(我应该先回答这篇文章)。这只是我们不想连接数据库或者对服务器做过多次请求,这是拖延处理速度的关键部分,因为它的连接和请求时间比计算机的处理时间长得多。因此,我们希望限制我们向服务器请求的时间。
改进我的示例的一个稍微好一点的方法是在getData(string sku)方法中执行两个SELECT查询,我可以使用INNER JOIN将它们组合起来,这样我们就可以摆脱一半的查询,这会略微改善运行时间
但是,最好的方法是将所有需要的数据放入一个表中并获取表,以便只需要一个查询(使用SqlDataAdapter中的Fill方法)。但是在一段时间内获取太多数据可能会导致运行时问题,因此您可能希望划分检索数据的时间(例如,一次检索200个数据),即使我们只需要执行50个查询(如果有10,000个数据) ,对每一个数据都做得好得多。