SqlBulkCopy.Close Method
Definition
Important
Some information relates to prerelease product that may be substantially modified before it’s released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
Closes the SqlBulkCopy instance.
public:
void Close();
public void Close ();
member this.Close : unit -> unit
Public Sub Close ()
Examples
The following example uses the same SqlBulkCopy instance to add sales orders and their associated details to two destination tables. Because the AdventureWorks sales order tables are large, the sample reads only orders placed by a certain account number and bulk copies those orders and details to the destination tables. The Close method is used only after both bulk copy operations are complete.
Important
This sample will not run unless you have created the work tables as described in Bulk Copy Example Setup. This code is provided to demonstrate the syntax for using SqlBulkCopy only. If the source and destination tables are in the same SQL Server instance, it is easier and faster to use a Transact-SQL INSERT ... SELECT
statement to copy the data.
using System.Data.SqlClient;
class Program
{
static void Main()
{
string connectionString = GetConnectionString();
// Open a connection to the AdventureWorks database.
using (SqlConnection connection =
new SqlConnection(connectionString))
{
connection.Open();
// Empty the destination tables.
SqlCommand deleteHeader = new SqlCommand(
"DELETE FROM dbo.BulkCopyDemoOrderHeader;",
connection);
deleteHeader.ExecuteNonQuery();
SqlCommand deleteDetail = new SqlCommand(
"DELETE FROM dbo.BulkCopyDemoOrderDetail;",
connection);
deleteDetail.ExecuteNonQuery();
// Perform an initial count on the destination
// table with matching columns.
SqlCommand countRowHeader = new SqlCommand(
"SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;",
connection);
long countStartHeader = System.Convert.ToInt32(
countRowHeader.ExecuteScalar());
Console.WriteLine(
"Starting row count for Header table = {0}",
countStartHeader);
// Perform an initial count on the destination
// table with different column positions.
SqlCommand countRowDetail = new SqlCommand(
"SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;",
connection);
long countStartDetail = System.Convert.ToInt32(
countRowDetail.ExecuteScalar());
Console.WriteLine(
"Starting row count for Detail table = {0}",
countStartDetail);
// Get data from the source table as a SqlDataReader.
// The Sales.SalesOrderHeader and Sales.SalesOrderDetail
// tables are quite large and could easily cause a timeout
// if all data from the tables is added to the destination.
// To keep the example simple and quick, a parameter is
// used to select only orders for a particular account
// as the source for the bulk insert.
SqlCommand headerData = new SqlCommand(
"SELECT [SalesOrderID], [OrderDate], " +
"[AccountNumber] FROM [Sales].[SalesOrderHeader] " +
"WHERE [AccountNumber] = @accountNumber;",
connection);
SqlParameter parameterAccount = new SqlParameter();
parameterAccount.ParameterName = "@accountNumber";
parameterAccount.SqlDbType = SqlDbType.NVarChar;
parameterAccount.Direction = ParameterDirection.Input;
parameterAccount.Value = "10-4020-000034";
headerData.Parameters.Add(parameterAccount);
SqlDataReader readerHeader = headerData.ExecuteReader();
// Get the Detail data in a separate connection.
using (SqlConnection connection2 = new SqlConnection(connectionString))
{
connection2.Open();
SqlCommand sourceDetailData = new SqlCommand(
"SELECT [Sales].[SalesOrderDetail].[SalesOrderID], [SalesOrderDetailID], " +
"[OrderQty], [ProductID], [UnitPrice] FROM [Sales].[SalesOrderDetail] " +
"INNER JOIN [Sales].[SalesOrderHeader] ON [Sales].[SalesOrderDetail]." +
"[SalesOrderID] = [Sales].[SalesOrderHeader].[SalesOrderID] " +
"WHERE [AccountNumber] = @accountNumber;", connection2);
SqlParameter accountDetail = new SqlParameter();
accountDetail.ParameterName = "@accountNumber";
accountDetail.SqlDbType = SqlDbType.NVarChar;
accountDetail.Direction = ParameterDirection.Input;
accountDetail.Value = "10-4020-000034";
sourceDetailData.Parameters.Add(accountDetail);
SqlDataReader readerDetail = sourceDetailData.ExecuteReader();
// Create the SqlBulkCopy object.
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(connectionString))
{
bulkCopy.DestinationTableName =
"dbo.BulkCopyDemoOrderHeader";
// Write readerHeader to the destination.
try
{
bulkCopy.WriteToServer(readerHeader);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
readerHeader.Close();
}
// Set up a different destination and
// map columns.
bulkCopy.DestinationTableName =
"dbo.BulkCopyDemoOrderDetail";
// Write readerDetail to the destination.
try
{
bulkCopy.WriteToServer(readerDetail);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
readerDetail.Close();
}
}
// Perform a final count on the destination
// tables to see how many rows were added.
long countEndHeader = System.Convert.ToInt32(
countRowHeader.ExecuteScalar());
Console.WriteLine("{0} rows were added to the Header table.",
countEndHeader - countStartHeader);
long countEndDetail = System.Convert.ToInt32(
countRowDetail.ExecuteScalar());
Console.WriteLine("{0} rows were added to the Detail table.",
countEndDetail - countStartDetail);
Console.WriteLine("Press Enter to finish.");
Console.ReadLine();
}
}
}
private static string GetConnectionString()
// To avoid storing the connection string in your code,
// you can retrieve it from a configuration file.
{
return "Data Source=(local); " +
" Integrated Security=true;" +
"Initial Catalog=AdventureWorks;";
}
}
Imports System.Data.SqlClient
Module Module1
Sub Main()
Dim connectionString As String = GetConnectionString()
' Open a connection to the AdventureWorks database.
Using connection As SqlConnection = New SqlConnection(connectionString)
connection.Open()
' Empty the destination tables.
Dim deleteHeader As New SqlCommand( _
"DELETE FROM dbo.BulkCopyDemoOrderHeader;", connection)
deleteHeader.ExecuteNonQuery()
deleteHeader.Dispose()
Dim deleteDetail As New SqlCommand( _
"DELETE FROM dbo.BulkCopyDemoOrderDetail;", connection)
deleteDetail.ExecuteNonQuery()
' Perform an initial count on the destination table
' with matching columns.
Dim countRowHeader As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderHeader;", _
connection)
Dim countStartHeader As Long = System.Convert.ToInt32( _
countRowHeader.ExecuteScalar())
Console.WriteLine("Starting row count for Header table = {0}", _
countStartHeader)
' Perform an initial count on the destination table
' with different column positions.
Dim countRowDetail As New SqlCommand( _
"SELECT COUNT(*) FROM dbo.BulkCopyDemoOrderDetail;", _
connection)
Dim countStartDetail As Long = System.Convert.ToInt32( _
countRowDetail.ExecuteScalar())
Console.WriteLine("Starting row count for Detail table = " & _
countStartDetail)
' Get data from the source table as a SqlDataReader.
' The Sales.SalesOrderHeader and Sales.SalesOrderDetail
' tables are quite large and could easily cause a timeout
' if all data from the tables is added to the destination.
' To keep the example simple and quick, a parameter is
' used to select only orders for a particular account as
' the source for the bulk insert.
Dim headerData As SqlCommand = New SqlCommand( _
"SELECT [SalesOrderID], [OrderDate], " & _
"[AccountNumber] FROM [Sales].[SalesOrderHeader] " & _
"WHERE [AccountNumber] = @accountNumber;", _
connection)
Dim parameterAccount As SqlParameter = New SqlParameter()
parameterAccount.ParameterName = "@accountNumber"
parameterAccount.SqlDbType = SqlDbType.NVarChar
parameterAccount.Direction = ParameterDirection.Input
parameterAccount.Value = "10-4020-000034"
headerData.Parameters.Add(parameterAccount)
Dim readerHeader As SqlDataReader = _
headerData.ExecuteReader()
' Get the Detail data in a separate connection.
Using connection2 As SqlConnection = New SqlConnection(connectionString)
connection2.Open()
Dim sourceDetailData As SqlCommand = New SqlCommand( _
"SELECT [Sales].[SalesOrderDetail].[SalesOrderID], " & _
"[SalesOrderDetailID], [OrderQty], [ProductID], [UnitPrice] " & _
"FROM [Sales].[SalesOrderDetail] INNER JOIN " & _
"[Sales].[SalesOrderHeader] " & _
"ON [Sales].[SalesOrderDetail].[SalesOrderID] = " & _
"[Sales].[SalesOrderHeader].[SalesOrderID] " & _
"WHERE [AccountNumber] = @accountNumber;", connection2)
Dim accountDetail As SqlParameter = New SqlParameter()
accountDetail.ParameterName = "@accountNumber"
accountDetail.SqlDbType = SqlDbType.NVarChar
accountDetail.Direction = ParameterDirection.Input
accountDetail.Value = "10-4020-000034"
sourceDetailData.Parameters.Add( _
accountDetail)
Dim readerDetail As SqlDataReader = _
sourceDetailData.ExecuteReader()
' Create the SqlBulkCopy object.
Using bulkCopy As SqlBulkCopy = _
New SqlBulkCopy(connectionString)
bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderHeader"
' Write readerHeader to the destination.
Try
bulkCopy.WriteToServer(readerHeader)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
readerHeader.Close()
End Try
' Set up a different destination and map columns.
bulkCopy.DestinationTableName = "dbo.BulkCopyDemoOrderDetail"
' Write readerDetail to the destination.
Try
bulkCopy.WriteToServer(readerDetail)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
readerDetail.Close()
End Try
End Using
' Perform a final count on the destination tables
' to see how many rows were added.
Dim countEndHeader As Long = System.Convert.ToInt32( _
countRowHeader.ExecuteScalar())
Console.WriteLine("{0} rows were added to the Header table.", _
countEndHeader - countStartHeader)
Dim countEndDetail As Long = System.Convert.ToInt32( _
countRowDetail.ExecuteScalar())
Console.WriteLine("{0} rows were added to the Detail table.", _
countEndDetail - countStartDetail)
Console.WriteLine("Press Enter to finish.")
Console.ReadLine()
End Using
End Using
End Sub
Private Function GetConnectionString() As String
' To avoid storing the connection string in your code,
' you can retrieve it from a configuration file.
Return "Data Source=(local);" & _
"Integrated Security=true;" & _
"Initial Catalog=AdventureWorks;"
End Function
End Module
Remarks
After you call a Close on the SqlBulkCopy object, no other operation will succeed. Calls to the WriteToServer method will throw an InvalidOperationException.
Calling the Close method from the SqlRowsCopied event causes an InvalidOperationException to be thrown.
Note that open SqlBulkCopy instances are closed implicitly at the end of a using
block.