为啥SqlClient 在传递SqlXml 时会使用不必要的XML 转换?

Posted

技术标签:

【中文标题】为啥SqlClient 在传递SqlXml 时会使用不必要的XML 转换?【英文标题】:Why does SqlClient use unnecessary XML conversion while passing SqlXml?为什么SqlClient 在传递SqlXml 时会使用不必要的XML 转换? 【发布时间】:2012-11-17 03:47:06 【问题描述】:

我有一个关于将 xml 数据类型传递给 C# 代码查询的问题。

首先,这是 SQL Server 上的一个表:

CREATE TABLE [dbo].[XmlTable](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [dat] [xml] NOT NULL
)

其次,我有一个用 C# 编写的应用程序。然后我从应用程序将行插入XmlTable

代码如下:

XDocument doc = new XDocument(new XElement("root",
     new XElement("abc", "123"),
     new XElement("cba", "321")));

var reader = new XmlTextReader(new StringReader(doc.ToString()));
var xml = new SqlXml(reader);

using (var connection = new SqlConnection(_connectionString))

     using (var command = new SqlCommand("insert into XmlTable (dat) values(@data)", connection))
     
          command.Parameters.Add(new SqlParameter("@data", SqlDbType.Xml)Value = xml);
          connection.Open();
          command.ExecuteNonQuery();
     

一切正常,插入行。但是如果我运行 SQL Profiler 并检查插入命令,我会看到以下内容:

declare @p3 xml
set @p3=convert(xml,N'<root><abc>123</abc><cba>321</cba></root>')
exec sp_executesql N'insert into XmlTable (dat) values(@data)',N'@data xml',@data=@p3

我们可以看到,尽管将SqlXml 类型传递给查询SqlClient 执行了从字符串到XML 的不必要的转换。 XML 解析器确实浪费了工作。

问题是:SqlClient 为什么会这样?以及如何在不进行额外转换的情况下做到这一点?

【问题讨论】:

此代码用于高负载场景,额外的转换使其变慢 Dmitriy:这是conversion(不是convertation 另外:您使用的是哪个版本的 SQL Server? 对不起我的英语:) 我用的是 2008 R2 别担心 - 你的英语比我的俄语好得多:-) 【参考方案1】:

现实中没有发生转换。您看到的是 Profiler/Trace 的工件,必须以某种方式将 TDS RPC 调用表示为 T-SQL 批处理,您可以复制粘贴并在 SSMS 中执行。执行的 real 文本只是 insert into XmlTable (dat) values(@data)@data 类型/值来自请求的 ParamData 部分。与 any 有线协议一样,序列化和编码必须在客户端进行,而解码和反序列化必须在服务器端进行。附带说明一下,也没有对 sp_execute_sql 的调用,这又是 Profiler/Trace 如何显示 RPC 调用的产物。

此代码用于高负载场景,额外的转换使其变慢

那是猜测。您应该基于measurements and observations 进行性能分析。

【讨论】:

以上是关于为啥SqlClient 在传递SqlXml 时会使用不必要的XML 转换?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用VIRTUALBOX虚拟机设置的内存使用量过高时会使实际机蓝屏死机?

为啥numpy点积函数在传递两个TensorFlow变量对象时会返回错误?

为啥在传递引用的参数时会得到“/bin/sh:参数列表太长”?

为啥传递给函数的协议默认值不会改变,即使函数在子类化时会改变?

为啥“git clone”在传递本地 file:/// url 时会打包对象数据库?

为啥我在尝试快速传递 segue 上的变量时会收到这些错误?