SqlBulkCopy to not insert IDENTITY field

B

Bryce K. Nielsen

I'm using SqlBulkCopy to copy over data from one table to another, BUT I
don't want the Identity field to be copied, and rather want the new server
to auto-generate the identity values. What's the best way to accomplish
this?

At first, I was hoping that I could just use WriteToServer and in my SELECT
statement, I would return NULL as my IDField. BUT that appears to break on
insert, with errors like "cannot insert NULL into identity field". So how do
I remove this field from my inserts?

-BKN
 
O

Otis Mukinfus

I'm using SqlBulkCopy to copy over data from one table to another, BUT I
don't want the Identity field to be copied, and rather want the new server
to auto-generate the identity values. What's the best way to accomplish
this?

At first, I was hoping that I could just use WriteToServer and in my SELECT
statement, I would return NULL as my IDField. BUT that appears to break on
insert, with errors like "cannot insert NULL into identity field". So how do
I remove this field from my inserts?

-BKN

If the Row ID is a an autoincrement column, then the answer is to not insert the
column. It will be updated automatically by SQL Server.
Good luck with your project,

Otis Mukinfus
http://www.arltex.com
http://www.tomchilders.com
 
B

Bryce K. Nielsen

If the Row ID is a an autoincrement column, then the answer is to not
insert the
column. It will be updated automatically by SQL Server.
Good luck with your project,

Yeah, I understand that, but my question was if there was an easy way to do
this with SqlBulkCopy without having to mess with mappings.

I don't think there is, instead what I've had to do was loop on the columns
and map every column but the first one. Fortunately for me, all the tables
have their Identity as the first field, so I can do this in a generic
function (i.e. for i gets 1 to ColumnCount-1, instead of 0 to
ColumnCount-1).

-BKN
 
D

David Sceppa [MSFT]

Bryce,

SqlBulkCopy will, exclude the identity column when inserting new rows
into the destination table. I've included a small C# sample to
demonstrate. The sample creates a small table with two columns and adds
three rows. The code retrieves the three rows into a DataTable and then
modifies the non-key column (so you can tell the originals and copies
apart) and the key column before adding these rows to the table via
SqlBulkCopy. Using the default SqlBulkCopyOptions, you'll see that the
identity values from the DataTable are ignored and that the database
generates new values for the identity column. If you change the code to
use SqlBulkCopyOptions.KeepIdentity, you would see the identity values from
the DataTable used.

I hope this information proves helpful.

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2006 Microsoft Corporation. All rights reserved.


string strConn, strSQL;
strConn = @"Data Source=.\SQLExpress;" +
"Initial Catalog=Northwind;Integrated Security=True;";
strSQL = "SELECT ID, OtherColumn FROM SqlBulkCopyTest";
using (SqlConnection cn = new SqlConnection(strConn))
{
cn.Open();
PrepDb(cn);

DataTable tbl = new DataTable();
SqlDataAdapter da = new SqlDataAdapter(strSQL, cn);
da.Fill(tbl);

foreach (DataRow row in tbl.Rows)
{
row["OtherColumn"] = ((string)row["OtherColumn"]).
Replace("Original", "Copied");
row["ID"] = ((int)row["ID"]) + 10;
}

SqlBulkCopyOptions options = SqlBulkCopyOptions.Default;
SqlBulkCopy bcp = new SqlBulkCopy(cn, options, null);
bcp.DestinationTableName = "SqlBulkCopyTest";
bcp.WriteToServer(tbl);

tbl.Clear();
da.Fill(tbl);
foreach (DataRow row in tbl.Rows)
Console.WriteLine("{0}: {1}", row["ID"], row["OtherColumn"]);
}

static void PrepDb(SqlConnection cn)
{
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText = "DROP TABLE SqlBulkCopyTest";
try { cmd.ExecuteNonQuery(); }
catch { }

cmd.CommandText = "CREATE TABLE SqlBulkCopyTest " +
"(ID int identity PRIMARY KEY, " +
"OtherColumn nvarchar(255))";
cmd.ExecuteNonQuery();

cmd.CommandText = "INSERT INTO SqlBulkCopyTest " +
"(OtherColumn) VALUES (@OtherColumn)";
SqlParameter p = cmd.Parameters.Add("@OtherColumn",
SqlDbType.NVarChar, 255);
p.Value = "First Original Row";
cmd.ExecuteNonQuery();
p.Value = "Second Original Row";
cmd.ExecuteNonQuery();
p.Value = "Third Original Row";
cmd.ExecuteNonQuery();
}
 
B

Bryce K. Nielsen

I finally figured out how to use the parameters in SqlBulkCopy. I thought
they would be properties I could set on the object after creation, but nope,
turns out they are only part of the constructor.

At any rate, I was avoiding looping on the DataReader and figured via trail
and error that SqlBulkCopy by default leaves out the Identity fields, so all
is good :)

-BKN
 
D

David Sceppa [MSFT]

At any rate, I was avoiding looping on the DataReader and figured
via trail and error that SqlBulkCopy by default leaves out the
Identity fields, so all is good :)

Glad to hear it, Bryce. Happy coding!

David Sceppa
Microsoft
This posting is provided "AS IS" with no warranties,
and confers no rights. You assume all risk for your use.
© 2006 Microsoft Corporation. All rights reserved.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top