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

Raj*_*mar 4 c# sql-server triggers sqlbulkcopy winforms

我正在使用SqlBulkCopy类在表中一次插入50k行tbl_recordsAfter 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);
Run Code Online (Sandbox Code Playgroud)

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

我想它应该为每一行开火.我怎样才能做到这一点??

usr*_*usr 8

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

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

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


Ema*_*sad 5

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

重要提示:usr 已经给出了答案,但我会稍微解释一下。

首先,这是微软文档中关于批量插入的内容,

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

FIRE_TRIGGERS 指定在大容量导入操作期间执行在目标表上定义的任何插入触发器。如果为目标表上的 INSERT 操作定义了触发器,则每个完成的批次都会触发它们。

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

如果您尝试将批量插入与SqlBulkCopy类(.Net Framework/Core)一起使用,则必须使用SqlBulkCopyOptionsEnum (文档)。

构造 SqlBulkCopy 实例时可以使用 SqlBulkCopyOptions 枚举来更改该实例的 WriteToServer 方法的行为方式。

这是一个样本,

var options = SqlBulkCopyOptions.CheckConstraints | SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.KeepIdentity;
var bulkCopy = new SqlBulkCopy(connectionString, options);
Run Code Online (Sandbox Code Playgroud)

好的。现在触发器将通过批量插入运行,但为什么只针对一条记录。FIRE_TRIGGER再次阅读微软关于争论的说法。

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

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

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

您可以在此处找到示例。