SqlDataAdapter 如何在内部工作?

Posted

技术标签:

【中文标题】SqlDataAdapter 如何在内部工作?【英文标题】:How SqlDataAdapter works internally? 【发布时间】:2012-12-19 23:02:05 【问题描述】:

我想知道SqlDataAdapter 在内部是如何工作的,尤其是在使用UpdateCommand 更新巨大的DataTable 时(因为它通常比从循环中发送sql 语句要快得多)。

这是我的一些想法:

它创建一个准备好的 sql 语句(使用 SqlCommand.Prepare()),其中填充了 CommandText,并使用正确的 sql 类型初始化了 sql 参数。然后循环需要更新的数据行,对每条记录更新参数值,调用SqlCommand.ExecuteNonQuery()。 它创建了一堆 SqlCommand 对象,里面填充了所有内容(CommandText 和 sql 参数)。然后一次将多个 SqlCommand 批处理到服务器(取决于 UpdateBatchSize)。 它使用一些特殊的、低级的或未记录的 sql 驱动程序指令,允许以有效的方式对多行执行更新(需要使用特殊的数据格式和相同的 sql 查询(@ 987654331@ 此处)将针对这些行中的每一行执行)。

【问题讨论】:

我经常想知道为什么那些询问某些事情在内部如何工作的人不使用 ILSpy 之类的东西,只是偷看一下。 我假设您已经连接了一个分析器(到数据库)来查看它的作用?你有什么问题? 正如@itsme86 所提到的,您可以使用 ILSpy - ilspy.net 获得很多乐趣。使用 Open From GAC 添加对 System.Data 的引用并进行探索! 【参考方案1】:

它使用称为命令集的 SQL Server 客户端类的内部工具。您可以使用单个命令将多个批次发送到 SQL Server。这减少了每次调用的开销。你有更少的服务器往返等等。

每个语句更新一行,每个批次发送一个语句,但每次往返发送多个批次。此列表中的最后一点是魔法酱

很遗憾,该设施未公开。 Ayende took a hack on this and built a private-reflection bases API for it.

如果您想了解更多信息,我鼓励您查看内部 SqlCommandSet 类。

也就是说,您自己可以比这更快:使用 TVP 传输更新数据并发出单个 UPDATE 来更新许多行。这样您就可以节省所有每批次、每往返和每条语句的开销。

这样的查询应该是这样的:

update T set T.x = @src.x from T join @src on T.ID = @src.ID

【讨论】:

好答案;尽管最后一条语句确实取决于更新的性质。我可能会添加一个指向 ILSpy 的链接,并强调 SqlCommandSet 是 SqlDataAdapter 中的一个私有字段。 @dash 我想不出这不是多行更新最快方法的情况。你能想到一个吗? 抱歉,我不清楚 - 我同意,我的意思是在原始帖子的上下文中,如果您使用许多不同的值更新了许多不同的行,那么实际上并没有您可以使用的单个 SQL 语句(有吗?!) @dash,你可以说update T set T.x = @src.x from T join @src on T.ID = @src.ID。这会立即更新所有内容,从 TVP 中提取数据。 非常对索引和索引视图维护非常有效。 我明白了!我以前没有遇到过TVP。我现在将(实际上是 ab)使用它们——能够为存储的过程或函数提供一个表是非常有用的。 mssqltips.com/sqlservertip/1483/…

以上是关于SqlDataAdapter 如何在内部工作?的主要内容,如果未能解决你的问题,请参考以下文章

ConcurrentHashMap 如何在内部工作?

PHP 的“未设置”构造如何在内部工作?

getObject 函数在内部如何工作?

哈希:它在内部是如何工作的?

分段错误如何在内部(内核/硬件)工作?

Java 分析器在内部是如何工作的?