Click here to Skip to main content
15,885,141 members
Articles / Database Development

Bulk Insert a .NET List to Database

Rate me:
Please Sign up or sign in to vote.
3.07/5 (10 votes)
31 Jan 2018CPOL2 min read 36.8K   1.2K   9   11
This article presents a simple and efficient way to bulk insert any .NET list to the database.

Introduction

The SqlBulkCopy class provides an efficient means to import data into a SQL Server database. Even so, out of the box, it supports data import only from one of the following types:

  • DataTable
  • DataRow[]
  • IDataReader

In this article, we will look at a simple yet efficient mechanism to bulk insert data from any IList<T> type.

Background

There are times when we may need to bulk upload information available in .NET objects to the DB. The SqlBulkCopy class lets one efficiently bulk load a SQL Server table with data from another source. However, to make use of this, we need to either implement IDataReader on every such type that needs to be bulk persisted or rebuild the data as a DataTable (DataRow[]).

Creating a DataTable version of the object data may not be desirable, especially when the data is huge.

On the other hand, implementing IDataReader on a type presents with an intimidating 33 methods to define:

  • GetName(int i):string
  • GetDataTypeName(int i):string
  • GetFieldType(int i):Type
  • GetValues(object[] values):int
  • GetBoolean(int i):bool
  • GetByte(int i):byte
  • GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length):long
  • GetChar(int i):char
  • GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length):long
  • GetGuid(int i):Guid
  • GetInt16(int i):short
  • GetInt32(int i):int
  • GetInt64(int i):long
  • GetFloat(int i):float
  • GetDouble(int i):double
  • GetString(int i):string
  • GetDecimal(int i):decimal
  • GetDateTime(int i):DateTime
  • GetData(int i):IDataReader
  • IsDBNull(int i):bool
  • this[int i]:object
  • this[string name]:object
  • Close():void
  • GetSchemaTable():DataTable

Luckily, only the following handful of methods need to be defined for a bulkcopy:

  • Dispose():void
  • GetValue(int i):object
  • IsDBNull
  • GetOrdinal(string name):int
  • FieldCount:int
  • Read():bool
  • Depth:int
  • IsClosed:bool
  • RecordsAffected:int

The DataReaderAdapter class presented here saves the effort of implementing this reduced set of methods as long as the data is presented as an IList<T>. The DataReaderAdapter wraps around the list and exposes itself as an IDataReader that can be directly consumed by the SqlBulkCopy’s ‘WriteToServer’ method.

Using the Code

Using the DataReaderAdapter is quite simple:

  • Instantiate a DataReaderAdapter with an IList of the type that needs to be persisted.
  • Pass the DataReaderAdapter to the SqlBulkCopy.WriteToServer() method.
C#
//Generate a list of 10,000 Customer records
var customers = _fixture.CreateMany<Customer>(10000).ToList();
var customerDr = new DataReaderAdapter<Customer>(customers);
 
using (var connection = new SqlConnection(_connectionString))
{
    connection.Open();
    var bulkCopy = new SqlBulkCopy(connection)
    {
        DestinationTableName = "[dbo].[Customer]",
        BatchSize = 1000
    };
    bulkCopy.WriteToServer(customerDr);
    bulkCopy.Close();
}

Running the Tests

Pre requisites

  1. Execute the Db script files under the AdapterTests/DbScripts folder on a SQL Server database.
    • Create_Table_Customer.sql
    • Create_Table_Skus.sql
  2. Modify the connection string in app.config to point to the above database.

The test cases demonstrate the following scenarios:

Should InsertListToDb

When the properties of the .NET type and the DB column names match exactly in terms of the Names and the order in which they are defined.

Should InsertListToDbWithColumnMappings

When the names of properties of the .NET type do not match with the DB column names.

In this case, the SqlBulkCopy needs to be provided with a list of column mappings that help it identify which properties go to what columns in DB.

History

  • 15th January, 2018: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
I am a fervent enthusiast with a deep passion for exploring new technologies and programming paradigms, constantly seeking to broaden my understanding and skills. With a strong belief in the power of knowledge sharing, I actively contribute to the community by disseminating what I've learned and assisting others on their coding journeys. My inherent curiosity drives me to question, investigate, and delve into a variety of subjects, making every project an opportunity for growth and innovation.

Comments and Discussions

 
QuestionStill useful in 2023 Pin
John V Zammit22-Sep-23 1:25
professionalJohn V Zammit22-Sep-23 1:25 
AnswerRe: Still useful in 2023 Pin
Praveen P R17-Nov-23 8:41
Praveen P R17-Nov-23 8:41 
PraiseVery useful Pin
Member 29282915-Nov-20 6:22
Member 29282915-Nov-20 6:22 
PraiseVery Usefull Pin
Member 36330403-Feb-18 9:50
Member 36330403-Feb-18 9:50 
GeneralRe: Very Usefull Pin
Praveen P R6-Feb-18 8:55
Praveen P R6-Feb-18 8:55 
SuggestionKeep it as Tip/Trick Pin
Ehsan Sajjad31-Jan-18 8:19
professionalEhsan Sajjad31-Jan-18 8:19 
GeneralRe: Keep it as Tip/Trick Pin
OriginalGriff31-Jan-18 8:26
mveOriginalGriff31-Jan-18 8:26 
PraiseRe: Keep it as Tip/Trick Pin
Praveen P R31-Jan-18 14:10
Praveen P R31-Jan-18 14:10 
QuestionWe do this a lot and we use FastMember to do this Pin
Sacha Barber15-Jan-18 0:53
Sacha Barber15-Jan-18 0:53 
AnswerRe: We do this a lot and we use FastMember to do this Pin
Praveen P R17-Jan-18 6:28
Praveen P R17-Jan-18 6:28 
GeneralRe: We do this a lot and we use FastMember to do this Pin
Sacha Barber29-Jan-18 7:15
Sacha Barber29-Jan-18 7:15 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.