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
SqlDataReader、SqlDataAdapter與SqlCommand的 区别的更多相关文章
- sqlDataAdapter和SqlCommand的区别
因为DataSet是离线的,所以SqlDataAdapter这个对象是连接DataSet和数据库的桥梁,所有对DataSet的操作(填充,更新等)都要通过他 ado.net数据访问有两种方式: 1.离 ...
- ADO.NET基础知识学习(SQLCOnnection&SQLCommand&SQLDataReader&SQLDataAdapter&DataSet)
通过ADO.NET技术,我们可以高效的完成客户端同数据库之间的数据访问操作,便于我们在客户端程序简便高效的访问以及获取数据库中的有用数据,同时也可以对数据库中的数据进行更新,即可以完成客户端与数据库之 ...
- C#中的一些复习。
摘自http://www.cnblogs.com/yuchengping/p/3151537.html 等日后自己来完善. 基本概念 1..NET是平台,C#是.NET上的一门语言. 2.C#的异常处 ...
- SqlCommand和SqlDataAdapter的区别
SqlDataAdapter对象 一.特点介绍1.表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接.2.在SqlDataAdapter和DataSet之 ...
- C# SqlCommand和SqlDataAdapter的区别
SqlCommand和SqlDataAdapter的区别 SqlCommand对应DateReader SqlDataAdapter对应DataSet SqlCommand的执行效率比较高,但 ...
- C#中ExecuteReader、ExecuteNonQuery、ExecuteScalar、SqlDataReader、SqlDataAdapter应该怎么用?
C#中ExecuteReader.ExecuteNonQuery.ExecuteScalar.SqlDataReader.SqlDataAdapter应该怎么用? (2013-10-16 13:21: ...
- SqlDataAdapter用法
SqlDataAdapter和SqlCommand区别: SqlCommand就是是命令了,可以用它来执行SQL命令: SqlDataAdapter就是数据适配器了,它是用于在数据源和数据集之间通讯的 ...
- C# ADO.NET SqlDataAdapter中传递参数
ADO.NET的SQL语句中,往往不是静态的语句,而是需要接受传递过来的参数,比如典型的登录功能,需要查找指定的用户名: string sqlQuery = "SELECT * FROM W ...
- 数据库之SqlDataAdapter
SqlDataAdapter 类 表示用于填充 DataSet 和更新 SQL Server 数据库的一组数据命令和一个数据库连接.无法继承此类. 命名空间:System.Data.SqlClient ...
随机推荐
- A CIRCULAR PROGRESSBAR STYLE USING AN ATTACHED VIEWMODEL
This blog post describes how to re-template the Silverlight ProgressBar control to render a circular ...
- Centos 6.5 下安装socket5代理
---恢复内容开始--- 1. 安装 先安装依赖库 yum -y install gcc gcc-c++ automake make pam-devel openldap-devel cyrus-sa ...
- oracle 中触发器增加存储过程commit问题
触发器无需commit也不能写commit触发器和触发它的DML是同一个事务DML提交了,触发器的操作也提交了,要不就一起回滚了 当然,如果你一定要在触发器里写COMMIT那就用自治事务相当于一个事务 ...
- 申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,立即注册可得25美元
申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,可以在国内任意一个支持万事达的ATM.POS机上取现和刷卡消费.Payoneer可以网上购物,购买国外的产品,对我们有一个好处就是利用 ...
- 怎样在EPLAN P8里创建自己想要的电气元件符号
1.打开Eplan P8 ,新建一个名为"新项目"的项目,然后选择菜单"工具"----"主数据"-----"符号库"-- ...
- UNIX环境高级编程笔记之文件I/O
一.总结 在写之前,先唠几句,<UNIX环境高级编程>,简称APUE,这本书简直是本神书,像我这种小白,基本上每看完一章都是“哇”这种很吃惊的表情.其实大概三年前,那会大三,我就买了这本书 ...
- 碰到一个在app内部浏览器锚点异常的问题
最近在做一个文章评论的功能,其中一个需求是:在提交完评论后,需要跳转到位于页面底部的评论区域,正常情况下location.href=http://m.hostname.cn/article#comme ...
- android xml解析添加到listview中的问题
一个问题不知什么原因,代码: public class OtherActivity extends ListActivity { @Override protected void onCreate(B ...
- java之接口interface
接口 1.多个无关的类可以实现同一个接口 2.一个类可以实现多个无关的接口 3.与继承关系类似,接口与实现类之间存在多态性 4.定义java类的语法格式 < modifier> class ...
- 【C语言】zz优先队列的实现
做一个题目时,看见解法中使用了优先队列,http://hawstein.com/posts/3.6.html . 颇为好奇,找资料学习了一下,顺便做个摘要. c++的用法: 转自:http://blo ...