SqlDataReader的内部工作原理和元数据

4

出于好奇和对更多见解的永恒渴望 :)

这里有一个CLR存储过程,通过以下代码将结果发送回客户端。 SqlDataRecord附加了SqlMetaData数组。每个SqlDataRecord都获得值,这些值通过管道发送到客户端。

SqlMetaData[] columns = new SqlMetaData[1];

columns[0] = new SqlMetaData("bool", SqlDbType.Bit);

SqlDataRecord record = new SqlDataRecord(columns);
SqlContext.Pipe.SendResultsStart(record);

foreach (bool b in bools)
{
     record.SetBoolean(0, b);

      SqlContext.Pipe.SendResultsRow(record);
}
SqlContext.Pipe.SendResultsEnd();

客户端代码:

SqlCommand cmd = new SqlCommand("CLR_SPROC", connection)

SqlDataReader reader = cmd.ExecuteReader();

int b = reader.GetOrdinal("bool"); // b == 0 because it was added in index 0 in the SqlMetaData array

所以,“bool”的序号变为零,因为它在第一个索引中被发现。有趣。

现在的问题是:

SqlServer是否对每个查询都像这样在内部工作?也就是说,当执行查询时,查询解析器是否提取最终选择中的列名,从中构建一个SqlMetaData数组,将其附加到SqlDataRecord并通过流发送回来?

因此,查询“SELECT a,b,c FROM table”

变成

SqlMetaData[] columns = new SqlMetaData[3];

columns[0] = new SqlMetaData("a", SqlDbType.Int);
columns[1] = new SqlMetaData("b", SqlDbType.Int);
columns[2] = new SqlMetaData("c", SqlDbType.Int);

 SqlDataRecord record = new SqlDataRecord(columns);
 SqlContext.Pipe.SendResultsStart(record);

foreach(...)
{
  record.SetInt32(0, a);
  record.SetInt32(1, b);
  record.SetInt32(2, c);
  SqlContext.Pipe.SendResultsRow(record);
}

2
这是一款复杂的软件。所有SQL客户端的参考源都可以从Microsoft获取,例如:SQLCommand.cs:http://referencesource.microsoft.com/#System.Data/data/System/Data/SqlClient/SqlCommand.cs - Simon Mourier
上面的链接已经失效(404),您可以查看SqlCommand.csSqlClient - surfmuggle
1个回答

2
SQL Server使用TDS协议(Tabular Data Stream)与客户端通信。TDS是一种流式协议,包括描述结果集的元数据,后跟结果集数据流。结果集中的记录包含相同数量的列、列名和数据类型,因此只需要发送一次处理结果集所需的元数据,而不是将其附加到每个记录上。
像SqlClient这样的客户端API将低级别的TDS结构公开为更高级别的对象,如SqlMetaData、SqlDataRecord和SqlDataReader。虽然您编写的是针对客户端API而不是直接针对TDS的代码,但您可能会发现对TDS通信的初步了解很有趣,因为它提供了SQL Server在幕后工作的视图。您可以在http://msdn.microsoft.com/en-us/library/dd304523.aspx找到有关TDS协议的详细信息。

非常有趣,连同参考来源网站,我会花些时间仔细阅读。谢谢。 - Serve Laurijssen
@Dan,我有一个问题,可能与SQL元数据有关。你能看一下吗? 问题似乎出在这里:columnIndex >= _metaData.Length,但我不知道该如何解决它。 - Pingpong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接