SqlDataAdapter如何在内部工作?
我想知道SqlDataAdapter
是如何在内部工作的,特别是在使用UpdateCommand
来更新巨大的DataTable
(因为它通常比从循环中发送sql语句快得多)。
这是我想到的一些想法:
- 它创建了一个准备好的sql语句(使用
SqlCommand.Prepare()
),并填充了CommandText
并使用正确的sql类型初始化了sql参数。 然后,它在需要更新的数据行上循环,并为每条记录更新参数值,并调用SqlCommand.ExecuteNonQuery()
。 - 它创建了一堆
SqlCommand
对象,里面填充了所有内容(CommandText
和sql参数)。 然后将多个SqlCommands一次性批处理到服务器(取决于UpdateBatchSize
)。 - 它使用一些特殊的,低级或无证的sql驱动程序指令,允许以有效的方式对多行执行更新(需要使用特殊数据格式和相同的sql查询(此处为
UpdateCommand
)提供要更新的行针对这些行中的每一行执行)。
它使用SQL Server客户端类的内部工具,称为命令集 。 您可以使用单个命令向SQL Server发送多个批处理。 这减少了每次呼叫的开销。 你有更少的服务器往返等。
每个语句更新一行,每个批次发送一个语句,但每个往返发送多个批次。 这个清单中的最后一点是神奇的酱汁 。
不幸的是,这个设施没有公开曝光 。 Ayende对此进行了攻击并为其构建了一个私有reflection基础API。
如果您想了解更多信息,我建议您查看内部SqlCommandSet
类。
也就是说, 您可以自己比这更快 :使用TVP传输更新数据并发出更新许多行的单个UPDATE
。 这样就可以保存所有按批次,每次往返和每个语句的开销。
这样的查询看起来像这样:
update T set Tx = @src.x from T join @src on T.ID = @src.ID