ใน .Net1.1 ไม่สะดวกอย่างยิ่งที่จะแทรกข้อมูลทั้งหมดใน DataTable ทั้งหมดลงในฐานข้อมูลเป็นชุด หรือโยกย้ายระหว่างแหล่งข้อมูลต่างๆ ใน .Net2.0 มีการเพิ่มคลาสใหม่หลายคลาสภายใต้เนมสเปซ SQLClient เพื่อช่วยเราโยกย้ายข้อมูลเป็นกลุ่มผ่าน DataTable หรือ DataReader แหล่งข้อมูลอาจมาจากฐานข้อมูลเชิงสัมพันธ์หรือไฟล์ XML หรือแม้แต่ผลลัพธ์ที่ส่งคืนโดย WebService คลาสที่สำคัญที่สุดอย่างหนึ่งคือคลาส SqlBulkCopy ซึ่งสามารถช่วยให้เราย้ายข้อมูลจากแหล่งข้อมูลไปยังฐานข้อมูลเป้าหมายได้อย่างง่ายดาย
ก่อนอื่นเรามาแสดงการใช้คลาสนี้ผ่านตัวอย่างง่ายๆ:
วันที่และเวลาเริ่มต้น;
โมฆะที่ได้รับการป้องกัน Button1_Click (ผู้ส่งวัตถุ EventArgs e)
-
startTime = DateTime.Now;
สตริง SrcConString;
สตริง DesConString;
SqlConnection SrcCon = SqlConnection ใหม่ ();
SqlConnection DesCon = SqlConnection ใหม่ ();
SqlCommand SrcCom = SqlCommand ใหม่();
SqlDataAdapter SrcAdapter = SqlDataAdapter ใหม่();
DataTable dt = DataTable ใหม่ ();
SrcConString=
ConfigurationManager.ConnectionStrings ["SrcDBConnectionString"].ConnectionString;
DesConString=
ConfigurationManager.ConnectionStrings ["DesDBConnectionString"].ConnectionString;
SrcCon.ConnectionString = SrcConString;
SrcCom.Connection = SrcCon;
SrcCom.CommandText = " SELECT * จาก [SrcTable]";
SrcCom.CommandType = CommandType.Text;
SrcCom.Connection.Open();
SrcAdapter.SelectCommand = SrcCom;
SrcAdapter.Fill(dt);
SqlBulkCopy DesBulkOp;
DesBulkOp = SqlBulkCopy ใหม่ (DesConString,
SqlBulkCopyOptions.UseInternalTransaction);
DesBulkOp.BulkCopyTimeout = 500000000;
DesBulkOp.SqlRowsCopied +=
ใหม่ SqlRowsCopiedEventHandler (OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count;
พยายาม
-
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
-
catch (ข้อยกเว้น เช่น)
-
lblResult.Text = อดีตข้อความ;
-
ในที่สุด
-
SrcCon.ปิด();
DesCon.ปิด();
-
}
โมฆะส่วนตัว OnRowsCopied (ผู้ส่งวัตถุ SqlRowsCopiedEventArgs args)
-
lblCounter.Text += args.RowsCopied.ToString() + " แถวถูกคัดลอก<Br>";
TimeSpan copyTime = DateTime.Now - startTime;
lblCounter.Text += "เวลาการคัดลอก:" + copyTime.Seconds.ToString() + "." + copyTime.Milliseconds.ToString() + " วินาที";
-
จากนั้นวิเคราะห์บรรทัดโค้ดเหล่านี้โดยละเอียด:
SqlBulkCopy DesBulkOp;
DesBulkOp = new SqlBulkCopy(DesConString, SqlBulkCopyOptions.UseInternalTransaction) ขั้นแรกให้สร้างอินสแตนซ์ SqlBulkCopy ระบุฐานข้อมูลเป้าหมาย การใช้ SqlBulkCopyOptions.UseInternalTransaction หมายความว่ามีการระบุการดำเนินการโยกย้ายในธุรกรรม การย้อนกลับจะเกิดขึ้น โปรดดู MSDN สำหรับตัวเลือกอื่นๆ
DesBulkOp.BulkCopyTimeout = 500000000;
ระบุเวลาหมดเวลาสำหรับการดำเนินการ
DesBulkOp.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnRowsCopied);
DesBulkOp.NotifyAfter = dt.Rows.Count;
พยายาม
-
DesBulkOp.DestinationTableName = "SrcTable";
DesBulkOp.WriteToServer(dt);
-
คุณลักษณะ NotifyAfter ระบุจำนวนแถวข้อมูลที่ต้องประมวลผลก่อนเหตุการณ์การแจ้งเตือน ในที่นี้จะระบุเป็นจำนวนแถวในตาราง และเพิ่มเหตุการณ์ SqlRowsCopied เพื่อส่งออกเวลาของกระบวนการย้ายทั้งหมด วิธีการ WriteToServer คัดลอกแหล่งข้อมูลไปยังฐานข้อมูลเป้าหมาย ก่อนที่จะใช้เมธอด WriteToServer คุณต้องระบุแอตทริบิวต์ DestinationTableName ซึ่งเป็นชื่อตารางของฐานข้อมูลเป้าหมายก่อน
เรายังสามารถกำหนดธุรกรรมได้ด้วยตัวเอง เช่น
SqlTransaction Transaction;
ธุรกรรม =
SrcCom.Connection.BeginTransaction();
SqlBulkCopy DesBulkOp;
DesBulkOp = SqlBulkCopy ใหม่ (SqlConnection ใหม่ (DesConString))
SqlBulkCopyOptions.Default,
การทำธุรกรรม);
ลอง
-
-
-
จับ{}
ในที่สุด
-
ธุรกรรม.กระทำ();
-
นอกจากนี้ยังมีคลาส SqlBulkCopyColumnMapping ที่อนุญาตให้แมปฟิลด์แหล่งข้อมูลกับฟิลด์ที่มีชื่อต่างกันในข้อมูลเป้าหมาย กล่าวคือ หากชื่อคอลัมน์ของข้อมูลเป้าหมายและข้อมูลต้นฉบับแตกต่างกัน คุณสามารถใช้คลาสนี้สำหรับการแมป:
SqlBulkCopyColumnMapping ColMap = SqlBulkCopyColumnMapping ใหม่ ("SrcCol", "DesCol");
DesBulkOp.ColumnMappings.Add(ColMap);
หรือคุณสามารถเพิ่มการแมปได้โดยตรง:
DesBulkOp.ColumnMappings.Add("SrcCol", "DesCol");
ปัญหาด้านประสิทธิภาพ:
ฉันใช้ตัวอย่างข้างต้นเพื่อทดสอบและย้ายข้อมูลประมาณ 20,000 รายการ ฉันควรจะบอกว่าประสิทธิภาพยังดีอยู่ นอกจากนี้ การใช้โปรไฟล์ SQL เพื่อตรวจสอบเหตุการณ์การย้ายข้อมูล คุณจะเห็นได้ว่ามีบันทึกคำขอน้อยมาก เพียงไม่กี่รายการเท่านั้น ว่ากันว่าการใช้ SqlBulkCopy สามารถลดเวลาในการย้ายข้อมูลได้อย่างมาก