• SqlDataReader,SqlDataAdapter与SqlCommand的一点总结.


    1.SqlDataReader,在线应用,需要conn.open(),使用完之后要关闭.

    SqlConnection conn = new SqlConnection(connStr);
     //conn.Open();
    SqlCommand cmd = new SqlCommand("select top 10 * from tuser", conn);
    SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
    while (reader.Read())
    {
        Console.WriteLine(reader.GetValue(2));
    }
    这段代码报错:ExecuteReader requires an open and available Connection. The connection's current state is closed.
    应该将conn.Open()打开.


    2.SqlDataAdapter,离线应用,不需要用conn.open(), 它把这部分功能给封装到自己内部了,不需要你来显式的去调用, 它直接将数据fill到dataset中.

    SqlCommand与ADO时代的Command一样,SqlDataAdapter则是ADO.NET中的新事物,它配合DataSet来使用。其实,DataSet就像是驻留在内存中的小数据库,在DataSet中可以有多张DataTable,这些DataTable之间可以相互关联,就像在数据库中表关联一样!SqlDataAdapter的作用就是将数据从数据库中提取出来,放在DataSet中,当DataSet中的数据发生变化时,SqlDataAdapter再将数据库中的数据更新,以保证数据库中的数据和DataSet中的数据是一致的!
    用微软顾问的话讲:DataAdapter就像是一把铁锹,它负责把数据从数据库“铲”到DataSet中,或者将数据从DataSet“铲”到数据库中!

    调用DataAdapter的Fill方法时, 它会打开到数据库的SqlConnection, 再通过创建一个SqlCommand和调用ExecuteReader的方式来执行命令, 然后, 通过一个隐式士创建的SqlDataReader, 从数据库读取数据, 结束行的读取之后, SqlDataReader和SqlConnection会被关闭.

    DefaultView是DataTable类的一个属性。可用DataView类为每个DataTable定义多个视图。


    用Reflacter察看一下SqlDataAdapter及其父类的原代码,其方法调用脉络如下:

    Fill(DataSet dataSet)->

    Fill(dataSet, 0, 0, "Table", selectCommand, fillCommandBehavior)->

    FillInternal(dataSet, null, startRecord, maxRecords, srcTable, command, behavior)->

    Fill(dataset, srcTable, reader, startRecord, maxRecords)->

    Fill(dataset, srcTable, reader, startRecord, maxRecords)->

    FillFromReader(dataSet, null, srcTable, container, startRecord, maxRecords, null, null)->

    FillLoadDataRow(mapping)->

    while (dataReader.Read())

    因此个人认为最精髓的一句总结就是:SqlDataAdapter内部获取数据是通过调用SqlDataReader来实现的,而两者都需要使用SqlConnection和SqlCommand。

    具体Reflacter察看一下SqlDataAdapter及其父类的原代码如下:

    2.1 SqlDataAdapter是DbDataAdapter的子类.

    public sealed class SqlDataAdapter : DbDataAdapter, IDbDataAdapter, IDataAdapter, ICloneable

    2.2 DbDataAdapter是一个抽象类,里面包含了Fill的具体实现.

    public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable
    {
      public override int Fill(DataSet dataSet)
      {
        int num;
        IntPtr ptr;
        Bid.ScopeEnter(out ptr, "<comm.DbDataAdapter.Fill|API> %d#, dataSet\n", base.ObjectID);
        try
        {
            IDbCommand selectCommand = this._IDbDataAdapter.SelectCommand;
            CommandBehavior fillCommandBehavior = this.FillCommandBehavior;
            num = this.Fill(dataSet, 0, 0, "Table", selectCommand, fillCommandBehavior);
        }
        finally
        {
            Bid.ScopeLeave(ref ptr);
        }
        return num;
      }

      protected virtual int Fill(DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
      {
        int num;
        IntPtr ptr;
        Bid.ScopeEnter(out ptr, "<comm.DbDataAdapter.Fill|API> %d#, dataSet, startRecord, maxRecords, srcTable, command, behavior=%d{ds.CommandBehavior}\n", base.ObjectID, (int) behavior);
        try
        {
            if (dataSet == null)
            {
                throw ADP.FillRequires("dataSet");
            }
            if (startRecord < 0)
            {
                throw ADP.InvalidStartRecord("startRecord", startRecord);
            }
            if (maxRecords < 0)
            {
                throw ADP.InvalidMaxRecords("maxRecords", maxRecords);
            }
            if (ADP.IsEmpty(srcTable))
            {
                throw ADP.FillRequiresSourceTableName("srcTable");
            }
            if (command == null)
            {
                throw ADP.MissingSelectCommand("Fill");
            }
            num = this.FillInternal(dataSet, null, startRecord, maxRecords, srcTable, command, behavior);
        }
        finally
        {
            Bid.ScopeLeave(ref ptr);
        }
        return num;
      }

      private int FillInternal(DataSet dataset, DataTable[] datatables, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior)
      {
        bool flag = null == command.Connection;
        try
        {
            IDbConnection connection = GetConnection3(this, command, "Fill");
            ConnectionState open = ConnectionState.Open;
            if (MissingSchemaAction.AddWithKey == base.MissingSchemaAction)
            {
                behavior |= CommandBehavior.KeyInfo;
            }
            try
            {
                QuietOpen(connection, out open);
                behavior |= CommandBehavior.SequentialAccess;
                using (IDataReader reader = null)
                {
                    reader = command.ExecuteReader(behavior);
                    if (datatables != null)
                    {
                        return this.Fill(datatables, reader, startRecord, maxRecords);
                    }
                    return this.Fill(dataset, srcTable, reader, startRecord, maxRecords);
                }
            }
            finally
            {
                QuietClose(connection, open);
            }
        }
        finally
        {
            if (flag)
            {
                command.Transaction = null;
                command.Connection = null;
            }
        }

      protected virtual int Fill(DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords)
      {
        int num;
        IntPtr ptr;
        Bid.ScopeEnter(out ptr, "<comm.DataAdapter.Fill|API> %d#, dataSet, srcTable, dataReader, startRecord, maxRecords\n", this.ObjectID);
        try
        {
            if (dataSet == null)
            {
                throw ADP.FillRequires("dataSet");
            }
            if (ADP.IsEmpty(srcTable))
            {
                throw ADP.FillRequiresSourceTableName("srcTable");
            }
            if (dataReader == null)
            {
                throw ADP.FillRequires("dataReader");
            }
            if (startRecord < 0)
            {
                throw ADP.InvalidStartRecord("startRecord", startRecord);
            }
            if (maxRecords < 0)
            {
                throw ADP.InvalidMaxRecords("maxRecords", maxRecords);
            }
            if (dataReader.IsClosed)
            {
                return 0;
            }
            DataReaderContainer container = DataReaderContainer.Create(dataReader, this.ReturnProviderSpecificTypes);
            num = this.FillFromReader(dataSet, null, srcTable, container, startRecord, maxRecords, null, null);
        }
        finally
        {
            Bid.ScopeLeave(ref ptr);
        }
        return num;
      }

      internal int FillFromReader(DataSet dataset, DataTable datatable, string srcTable, DataReaderContainer dataReader, int startRecord, int maxRecords, DataColumn parentChapterColumn, object   parentChapterValue)
      {
        int num2 = 0;
        int schemaCount = 0;
        do
        {
            if (0 < dataReader.FieldCount)
            {
                SchemaMapping mapping = this.FillMapping(dataset, datatable, srcTable, dataReader, schemaCount, parentChapterColumn, parentChapterValue);
                schemaCount++;
                if (((mapping != null) && (mapping.DataValues != null)) && (mapping.DataTable != null))
                {
                    mapping.DataTable.BeginLoadData();
                    try
                    {
                        if ((1 == schemaCount) && ((0 < startRecord) || (0 < maxRecords)))
                        {
                            num2 = this.FillLoadDataRowChunk(mapping, startRecord, maxRecords);
                        }
                        else
                        {
                            int num3 = this.FillLoadDataRow(mapping);
                            if (1 == schemaCount)
                            {
                                num2 = num3;
                            }
                        }
                    }
                    finally
                    {
                        mapping.DataTable.EndLoadData();
                    }
                    if (datatable != null)
                    {
                        return num2;
                    }
                }
            }
        }
        while (this.FillNextResult(dataReader));
        return num2;
      }

      private int FillLoadDataRow(SchemaMapping mapping)
      {
        int num = 0;
        DataReaderContainer dataReader = mapping.DataReader;
        if (!this._hasFillErrorHandler)
        {
            while (dataReader.Read())
            {
                mapping.LoadDataRow();
                num++;
            }
            return num;
        }
        while (dataReader.Read())
        {
            try
            {
                mapping.LoadDataRowWithClear();
                num++;
                continue;
            }
            catch (Exception exception)
            {
                if (!ADP.IsCatchableExceptionType(exception))
                {
                    throw;
                }
                ADP.TraceExceptionForCapture(exception);
                this.OnFillErrorHandler(exception, mapping.DataTable, mapping.DataValues);
                continue;
            }
        }
        return num;
      }

    }

  • 相关阅读:
    codeforces 459 C. Pashmak and Buses(思维)
    poj 2763 Housewife Wind(树链剖分+单点查询+区间修改)
    codeforces E. Phone Talks(dp)
    BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分+单点更新+区间求和+区间求最大值)
    SPOJ
    hdu 3966 Aragorn's Story(树链剖分+区间修改+单点查询)
    codeforces H. Queries for Number of Palindromes(区间dp)
    codeforces 245 D. Restoring Table(位运算+思维)
    codeforces 402 D. Upgrading Array(数论+贪心)
    codeforces 793 D. Presents in Bankopolis(记忆化搜索)
  • 原文地址:https://www.cnblogs.com/liuzhendong/p/2330689.html
Copyright © 2020-2023  润新知