استخدام SqlBulkCopy في ADO.NET

-

نحتاج في بعض الحالات إلى إدراج كمية كبيرة من السجلات في قاعدة البيانات، على سبيل المثال 1 مليون سجلاو اكثر ، تحتوي ADO.NET على class يسمى SqlBulkCopy والذي يقوم بهذا العمل بسرعة كبيرة.

يحتوي SqlBulkCopy  على طريقة تسمى ()WriteToServer  تأخذ SqlDataReader object,  ، ومن خلال هذه الطريقة تتم عمليات bulk inserts  بسرعة.

لنفترض عندنا جدول خاص بالطلاب في قاعدة البيانات باسم AccountData يحتوي على مليون سجل، والمطلوب نسخ جميع هذه السجلات إلى جدول آخر باسم Accounts. في هذه الحاله بنستخدم SqlBulkCopy class.
فيما يلي الكود الخاص بانشاء الجداول:

CREATE TABLE [dbo].[AccountData] (
    [Id]    INT          IDENTITY (1, 1) NOT NULL Primary key,
    [PersonName]  VARCHAR (50) NOT NULL,
    [TotalCash] MONEY        NOT NULL
);
CREATE TABLE [dbo].[Account] (
    [Id]    INT          IDENTITY (1, 1) NOT NULL Primary key,
    [Name]  VARCHAR (50) NOT NULL,
    [Money] MONEY        NOT NULL
);
تمام نشوف كيف ممكن نسخ البيانات وعلى فرض عندنا عدد كبير من البيانات داخل الجداول.

أضف Controller جديد باسم TransferDataController ثم قم بإضافة actions باسم TransferData  وبعدها نضيف الكود التالي:

public IActionResult TransferData()
{
    return View();
}
  
[HttpPost]
[ActionName("TransferData")]
public IActionResult TransferData_Post()
{
    string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
    SqlConnection connection = new SqlConnection(connectionString);
    string sql = $"Select * From AccountData";
    SqlCommand command = new SqlCommand(sql, connection);
    connection.Open();
    SqlDataReader dataReader = command.ExecuteReader();
    // create a SqlBulkCopy object
    SqlBulkCopy sqlBulk = new SqlBulkCopy(connection);
    //Give your Destination table name
    sqlBulk.DestinationTableName = "Account";
    //Mappings
    sqlBulk.ColumnMappings.Add("PersonName", "Name");
    sqlBulk.ColumnMappings.Add("TotalCash", "Money");
    //Copy rows to destination table
    sqlBulk.WriteToServer(dataReader);
    return View();
}
تم استخدام SqlDataReader object لقراءة البيانات من AccountData table:
الكود:
SqlDataReader dataReader = command.ExecuteReader();

بعد ذلك قمنا بإنشاء كائن SqlBulkCopy بتمرير SqlConnection object إليه:
الكود:
SqlBulkCopy sqlBulk = new SqlBulkCopy(connection);
الهدف هو إخبار SqlBulkCopy object بكيفية إجراء نسخ البيانات، نحتاج إلى تحديد اسم الجدول الذي سيتم النسخ اليه مثل:
الكود:
sqlBulk.DestinationTableName = "Account";
يجب أيضًا تحديد column mappings، باستخدام طريقة ()ColumnMappings.Add  تأخذ هذه الطريقة 2 parameters:
  • اسم العمود في الجدول المصدر كمعامل أول Source table column’s name as first parameter
  • اسم العمود في الجدول الذي سيتم النسخ اليه كمعلمة ثانية Destination table column’s name as second parameter
الكود:
sqlBulk.ColumnMappings.Add("PersonName", "Name");
sqlBulk.ColumnMappings.Add("TotalCash", "Money");
أخيرًا ، نستخدم طريقة ()WriteToServer  لبدء عملية النسخ ، مثل:
sqlBulk.WriteToServer(dataReader);

انشاء View
قم بإنشاء View باسم TransferData في مجلد Views ➤ TransferData وأضف الكود التالي إليه:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ADO - Transfer Data</title>
    <link rel="stylesheet" asp-href-include="lib/bootstrap/css/bootstrap.min.css" />
</head>
<body>
    <div class="container-fluid">
        <h1>Transfer data from SqlBulkCopy class</h1>
        <form method="post">
            <button type="submit" class="btn btn-sm btn-primary">Transfer Data</button>
        </form>
    </div>
</body>
</html>
عند النقر فوق الزر " Transfer Data " ، سيتم استدعاء TransferData action وسيتم تنفيذ كود SqlBulkCopy.