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 如何在内部工作?的主要内容,如果未能解决你的问题,请参考以下文章