DataAdpater的Fill研究

DataAdpater的Fill研究一直在思考,DataAdapter到底是怎么把数据Fill给一个DataSet的,最主要的是与DataReader的读取有什么不同今天终于坐不住了,为了满足,研究了一番,使用工具:Reflector,EditPlus过程如下:先用Reflector把System.Data给脱了,然后关闭(废话)从SqlDataAdapter入手。打开SqlDataAdapter,代码不多,只有SelectComm…

DataAdpater的Fill研究

一直在思考,DataAdapter到底是怎么把数据Fill给一个DataSet的,最主要的是与DataReader的读取有什么不同
今天终于坐不住了,为了满足,研究了一番,使用工具:Reflector,EditPlus

过程如下:

先用Reflector把System.Data给脱了,然后关闭(废话)
从SqlDataAdapter入手。打开SqlDataAdapter,代码不多,只有SelectCommand,InsertCommand这些属性和成员
然 后从(public sealed class SqlDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter, ICloneable)得知,要去摸DbDataAdapter了。顺便骂了句,竟然sealed不让我重用,%&(^&*($% &
估计DbDataAdapter在System.Data.Common下,果然找到了。声明如下:(public abstract class DbDataAdapter : DataAdapter, ICloneable)
刚才吓到了,这次直接先摸摸DbDataAdapter的爹类DataAdapter,发现只有构造函数,dispose、update等方法,就是实现最基本的功能的方法。恩,安心了,继续DbDataAdapter
DataAdapter最简单的,直接Fill一个DataSet,所以先找这个方法,估计其内部是调用另外一个方法,果然没错。代码如下:
public override int Fill(DataSet dataSet)
{

    return this.Fill(dataSet, 0, 0, “Table”, this.SelectCommand, CommandBehavior.Default);
}
然后,找到其调用的方法的定义,惊奇地,这个方法还是个protected virtual:
protected virtual int Fill(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
{

    if (dataSet == null)
    {

    throw ADP.FillRequires(“dataSet”);
    }
    if (command == null)
    {

    throw ADP.MissingSelectCommand(“Fill”);
    }
    if (startRecord < 0)
    {

    throw ADP.InvalidStartRecord(“startRecord”, startRecord);
    }
    if (maxRecords < 0)
    {

    throw ADP.InvalidMaxRecords(“maxRecords”, maxRecords);
    }
    if (ADP.IsEmpty(srcTable))
    {

    throw ADP.FillRequiresSourceTableName(“srcTable”);
    }
    return this.FillFromCommand(dataSet, startRecord, maxRecords, srcTable, command, behavior);
}
可以看出,前面的if都只是判断传入参数,非法就往外扔异常。最后一句才是正主。好奇地打开了ADP.CS,里面的方法都是返回异常的,就不列出来了。
然后,开始吃主餐。找到了FillFromCommand,不长,核心代码如下:
try
{

    DbDataAdapter.QuietOpen(connection1, out state1);
    using (IDataReader reader1 = command.ExecuteReader(behavior | CommandBehavior.SequentialAccess))
    {

    if (data is DataTable)
    {

        return this.Fill((DataTable) data, reader1);
    }
    return this.Fill((DataSet) data, srcTable, reader1, startRecord, maxRecords);
    }
}
finally
{

    DbDataAdapter.QuietClose(connection1, state1);
}
又要开始找了,我已经要问候别人母亲了,不过还是有收获的,原来Fill用的还是DataReader!!
我直接找Fill((DataSet) data。。。)的定义,发现除了参数判断抛异常,就是直接传递给FillFromReader

然后我写的累了,后面一大堆步奏描述跳过,直接讲道理:

1.DataTable的Column的生成,是通过SchemaMapping获得DataReader的Schema然后setup到DataTable的

2.QuietOpen和QuietClose就是简单的打开和关闭,Quiet命名打头意思就是不让你在外部知道的而已。

3.在FillLoadDataRowChunk中,数据装载还是从SchemaMapping和其DataReader来Read的

4.CommandBehavior.SequentialAccess是有点用的,baidu一下,查得资料如下:

默 认情况下,DataReader 每次 Read 时都要把整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,就把 CommandBehavior.SequentialAccess 传递给 ExecuteReader 调用。这将 DataReader 的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior.SequentialAccess 要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能再读它的值了。   
如果已经完成读取来自 DataReader 的数据,但仍然有大量挂起的未读结果,就在调用 DataReader 的 Close 之前先调用 Command 的 Cancel。调用 DataReader 的 Close 会导致在关闭游标之前检索挂起的结果并清空流。调用 Command 的 Cancel 会放弃服务器上的结果,这样,DataReader 在关闭的时候就不必读这些结果。如果要从 Command 返回输出参数,还要调用 Cancel 放弃它们。如果需要读取任何输出参数,不要调用 Command 的 Cancel,只要调用 DataReader 的 Close 即可。

结论:DataAdapter其实就是封装了DataReader读取数据然后填充数据容器的类
人家命名也很清楚了,我就是个Adapter,是个托。

转载于:https://www.cnblogs.com/erik168/archive/2007/01/26/631464.html

今天的文章DataAdpater的Fill研究分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/31654.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注