Similar to these other questions noted below, I have two tables with the structure:
create table parent (
recno int identity(1,1) primary key not null,
Create two staging tables with the same structure as your target tables but don't use identity on recno column.
create table parentTmp (
recno int,
groupCode int,
parentdata varchar(80)
);
create table childTmp (
parentrecno int not null,
childdata varchar(80)
)
Bulk load your data to the staging tables, keeping the recno/parentrecno values as is.
Then you can use merge and output to move the data from the staging tables.
-- Table variable to hold mapping between
-- SourceRecno and TargetRecno
declare @recno table(SourceRecno int, TargetRecno int);
-- Merge data from parentTmp to parent
-- Output old and new recno to @recno
merge parent T
using parentTmp S
on 0=1
when not matched then
insert (groupCode, parentdata)
values (S.groupCode, S.parentData)
output S.recno, inserted.recno into @recno;
-- Copy data from childTmp to child
-- Use @recno to get the new recno
insert into child(parentrecno, childdata)
select R.TargetRecno, C.childdata
from childTmp as C
inner join @recno as R
on C.parentrecno = R.SourceRecno;
This will only work in SQL Server 2008 (and later I presume).
This is not an absolut bulk insert, but instead it inserts all child data at the same time with the parent data, making only 1 round trip to the DB.
insert into parent(groupcode, parentdata) values(1, 'parent data');
insert into child(parentrecno, childdata) select parentrecno, childdata from (
select SCOPE_IDENTITY() as parentrecno, 'child data 1' as childdata
union
select SCOPE_IDENTITY() as parentrecno, 'child data 2' as childdata
union
select SCOPE_IDENTITY() as parentrecno, 'child data 3' as childdata
) childrendata;
You can build scripts like this in your C# code, and then perform one request per parent.
Be aware that this may not be a good approach if the amount of child data is known to be large. Don't know the details, but I'm sure that the size of the sql script can't grow indefinitely.