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;
  }

}

轉載自:SqlDataReader,SqlDataAdapter与SqlCommand的一点总结. http://www.cnblogs.com/liuzhendong/archive/2012/01/28/2330689.html

时间: 2024-10-16 23:53:49

SqlDataReader、SqlDataAdapter與SqlCommand的 区别的相关文章

C#中ExecuteReader、ExecuteNonQuery、ExecuteScalar、SqlDataReader、SqlDataAdapter应该怎么用?

对于C#初学者来说,我们通常遇到ExecuteReader.ExecuteNonQuery.ExecuteScalar.SqlDataReader.SqlDataAdapter这些对象或者方法的时候就开始犯晕,不知道哪个对象适合用增删改,哪个对象适合查询的时候用,本人通过 网上搜索和个人的一些理解,整理了一下,有错误的地方希望大家能给出指正. 一.//数据库连接字符串    private readonly static string connectionString =      Config

sqlcommand ,sqldataadapter, dataset学习记录 —转自kaisir

sqlconnection数据库连接对象:只有联接才能进行其它操作 sqldataadapter数据适配器对象,就是用某个sqlconnection,执行某个查询语句(SELECT语句),放到某个DataSet里 sqlcommand 数据命令对象(SELECT,INSERT,DELETE,UPDATE等,还可以是存储过程) SqlCommand.Parameter属性传sql参数 ExecuteScalar :执行查询,返回单个字段,比如求和的结果,平均值,最大最小值等等 ExecuteRea

sqlcommand ,sqldataadapter, dataset —————转

sqlconnection数据库连接对象:只有联接才能进行其它操作 sqldataadapter数据适配器对象,就是用某个sqlconnection,执行某个查询语句(SELECT语句),放到某个DataSet里 sqlcommand 数据命令对象(SELECT,INSERT,DELETE,UPDATE等,还可以是存储过程) SqlCommand.Parameter属性传sql参数 ExecuteScalar :执行查询,返回单个字段,比如求和的结果,平均值,最大最小值等等 ExecuteRea

SqlBulkCopy(批量复制)使用方法 &amp;&amp; SqlDataAdapter Update

SqlBulkCopy提供了一种将数据复制到Sql Server数据库表中高性能的方法.SqlBulkCopy 包含一个方法 WriteToServer,它用来从数据的源复制数据到数据的目的地. WriteToServer方法可以处理的数据类型有DataRow[]数组,DataTable 和 DataReader. 你可以根据不同的情形使用不同的数据类型.SqlBulkCopy其原理是采用了SQL Server的BCP协议进行数据的批量复制. SqlBulkCopy(批量复制):批量复制速度极快

Ado.NET SqlDataReader详解

ado.net的数据提供程序有三个分别是SqlServer数据提供程序,OLE DB提供程序,ODBC提供程序. 本次记录的是SqlServer提供程序中的一些知识点. ①SqlDataReader必须经过SqlCommand调用DataReader来进行实例化.该类的特点是只读,访问速度快. 通过Read方法从数据源中拉取数据,每次读取时只能获取到一条记录(只读),在这期间要保持与数据库的连接,本地DataReader并不对数据进行缓存.当对大量数据进行检索的时候,速度是很不错的.其中重要的一

ADO.Net之SqlConnection、 Sqlcommand的应用学习心得(思维导图,知识解析,案例分析)

ADO.Net之SqlConnection. Sqlcommand的应用 一.思维导图: ADO.NET与SQL连接: 二.知识点介绍: SqlConnection和Sqlcommand都是组成数据提供程序的类. SqlConnection使用它来建立和数据库的连接,Sqlcommand使用它执行SQL命令和存储过程. ADO.NET有两种类型的对象:基于连接的和基于内容的,SqlConnection和Sqlcommand属于基于连接的,它们连接到数据库,执行SQL语句,遍历只读结果集或者填充D

C#使用SqlDataReader读取数据库数据时CommandBehavior.CloseConnection参数的作用

主要用在ExecuteReader(c)中,如果想要返回对象前不关闭数据库连接,须要用CommandBehavior.CloseConnection: CloseConnection解决了流读取数据模式下,数据库连接不能有效关闭的情况.当某个XXXDataReader对象在生成时使用了CommandBehavior.CloseConnection,那数据库连接将在XXXDataReader对象关闭时自动关闭. 由于流模式读取数据库的特点,在具体应用时很难确定数据库连接何时才能被关闭,因为读取的动

数据适配器SqlDataAdapter学习笔记

SqlDataAdapter(数据适配器) 是 DataSet 和 SQL Server 之间的桥接器,用于检索和保存数据.SqlDataAdapter 与 SqlConnection 和 SqlCommand 一起使用,以便在连接到 SQL Server 数据库时提高性能.下面结合我们做的医院药库管理系统中厂商资料的新建和维护这一功能来说明适配器的用法. private void 厂商资料新建和维护_Load(object sender, EventArgs e)        {      

S2 第二本书 深入.NET平台和C#编程 总结 by天命

第一章 深入.NET框架 .NET框架 包含 CLR公共语言运行时 FCL框架类库 CLR(Common Language Runtime)公共语言运行时 CLS(Common Language Specific)公共语言规范 CTS(Common Type System)公共类型系统 FCL(Framework Class Library)框架类库 基本框架类(线程 ADO.NET XML类 文件IO类...... Web窗体 MVC WinForms ADO.NET SqlConnectio