使用SqlBulkCopy为每个插入的行触发触发器

时间:2013-09-25 10:53:19

标签: c# sql-server winforms triggers sqlbulkcopy

我正在使用SqlBulkCopy类在表tbl_records中一次插入50k行 我在此表上设置了After Insert触发器并使用以下代码

SqlBulkCopy SqlBc1 = new SqlBulkCopy(strConnString, SqlBulkCopyOptions.FireTriggers);

// Set DataReader For SqlBulkCopy

sqlComm = new SqlCommand(strQuery, sqlTemCon);
sqlComm.CommandTimeout = 3600000;
sqlComm.CommandType = System.Data.CommandType.Text;
SqlDataReader dReader = sqlComm.ExecuteReader();       
SqlBc1.WriteToServer(dReader);

但执行前后。它只触发50k插入的First

我想它应该为每一行开火。我怎么能这样做?

4 个答案:

答案 0 :(得分:8)

触发器永远不会每行触发。它们为相应的DML语句的所有行触发。重写您的触发器,以便它可以处理包含许多行的INSERTED表。无论如何,这是最佳实践和必修课。

  

它只触发了从50k行插入的第一行

你必须误解情况,可能是因为你不知道触发器可以在虚拟表中包含多行。

答案 1 :(得分:4)

默认情况下,SqlBulkCopy对象的批量大小是完整的行集。

以下是MSDN对BatchSize属性值的说法: “零(默认值)表示每个WriteToServer操作都是一个批处理。”

在这种情况下,触发器将触发一次,但Inserted表将包含所有受影响记录的条目。

答案 2 :(得分:4)

如果其他人遇到此问题并寻求解决方案,我也会在这里发布我的发现。

重要:usr已经给出了答案,但我会稍作解释。

首先,这就是Microsoft documentation关于批量插入的说法,

如果未指定FIRE_TRIGGERS,则不会执行插入触发器。

FIRE_TRIGGERS指定在 在批量导入操作期间执行目标表。如果 触发器是为目标表上的INSERT操作定义的,它们 每个完成的批次都会被解雇。

FIRE_TRIGGERS是与BULK INSERT T-SQL语句一起使用的参数。

如果您尝试对SqlBulkCopy类(.Net Framework / Core)使用批量插入,则必须使用SqlBulkCopyOptions枚举(docs)。

当您构造一个A时可以使用SqlBulkCopyOptions枚举 SqlBulkCopy实例更改该方法的WriteToServer方法 实例行为。

这是一个样本,

var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.KeepIdentity;
var bulkCopy = new SqlBulkCopy(connectionString, options);

好。现在触发器将与批量插入一起运行,但是为什么只有一条记录。再次阅读Microsoft关于FIRE_TRIGGER参数的说法。

如果为目标表上的INSERT操作定义了触发器, 每个完成的批次都会被解雇。

这意味着您的触发器将一次运行整个批次。但是您的批次包含多个行。因此,您的触发算法(您应该对一条记录执行的操作)将只适用于一条记录,而不适用于所有记录。

现在您知道了为什么它不适用于所有人,因此解决方案是改善触发器以处理多行。这意味着迭代抛出INSERTED临时表附带的所有行,并对所有记录执行算法。您可以使用CURSOR或简单的WHILE LOOP。由你决定。

您可以找到示例here

答案 3 :(得分:0)

我试过这个,它会起作用。

我希望它能帮到你..

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