I am using SqlBulkCopy
class to insert 50k rows at a time in table tbl_records
I have set a After Insert
trigger on this table and usi
I Have try this and it will work for.
I hope its help you..
CREATE TRIGGER Triggername ON TableName
After INSERT
AS
SET NOCOUNT ON;
insert into TargetTable (Fields) SELECT (i.field1,i.field2,i.field3,....,i.fieldn) FROM inserted i GO
In case another person come across this problem and looking for a solution, here I will post my findings as well.
IMPORTANT: usr has already given the answer, but I will explain it a little bit.
First, this is what Microsoft documentation says about bulk insert,
If FIRE_TRIGGERS is not specified, no insert triggers execute.
FIRE_TRIGGERS Specifies that any insert triggers defined on the destination table execute during the bulk-import operation. If triggers are defined for INSERT operations on the target table, they are fired for every completed batch.
FIRE_TRIGGERS
is a argument use with BULK INSERT
T-SQL statement.
And if you are trying to use bulk insert with SqlBulkCopy
class (.Net Framework/Core) you have to use SqlBulkCopyOptions
Enum (docs).
You can use the SqlBulkCopyOptions enumeration when you construct a SqlBulkCopy instance to change how the WriteToServer methods for that instance behave.
Here is a sample,
var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.KeepIdentity;
var bulkCopy = new SqlBulkCopy(connectionString, options);
OK. Now triggers will run with bulk insert, But why for only one record. Read what Microsoft said about FIRE_TRIGGER
argument again.
If triggers are defined for INSERT operations on the target table, they are fired for every completed batch.
That means, your trigger will run for whole batch at once. But your batch contains more than one row. Therefore your trigger algorithm (The thing you supposed to do to a single record) will work for one record, not for all the records.
Now you know why it doesn't work for all, so the solution is improve your trigger to work with multiple rows. Which means iterate throw all rows comes with INSERTED
temporary table and execute your algorithm for all records. You can use CURSOR
or a simple WHILE LOOP
. Its up to you.
You can find examples here.
Triggers never fire per-row. They fire for all rows of the corresponding DML statement. Rewrite your trigger so that it can cope with the INSERTED
table containing many rows. This is best-practice and required practice anyway.
it is firing trigger for only first row inserted out of 50k rows
You must be misinterpreting the situation, maybe because you were unaware that triggers can contain multiple rows in the virtual tables.
The SqlBulkCopy object's batch size is the full set of rows, by default.
Here's what MSDN says about the BatchSize property values: "Zero (the default) indicates that each WriteToServer operation is a single batch."
In this case, the trigger will fire once, but the Inserted table will have entries for all of the affected records.