ado.net中的 sqlconnection sqlcommand datareader dataset SqlDataAdapter之间的关系
Connection:
和数据库交互,必须连接它。连接帮助指明数据库服务器、数据库名字、用户名、密码,和连接数据库所需要的其它参数。Connection对象会被Command对象使用,这样就能够知道是在哪个数据源上面执行命令。
Command:
Command对象就是用来执行数据库操作命令的。比如对数据库中数据表的插入,删除,更新等都要通过Command对象来实现的。可以执行查询(SELECT语句),执行插入(INSERT语句),执行更新(UPDATE语句),执行删除(DELETE语句)。这个对象是架构在Connection 对象上,也就是Command 对象是透过连结到数据源。
DataReader:
当我们只需要循序的读取数据而不需要其它操作时,可以使用DataReader 对象。DataReader对象只是一次一笔向下循序的读取数据源中的数据,而且这些数据是只读的,并不允许作其它的操作。因为DataReader 在读取数据的时候限制了每次只读取一笔,而且只能只读,所以使用起来不但节省资源而且效率很好。使用DataReader 对象除了效率较好之外,因为不用把数据全部传回,故可以降低网络的负载。ADO.NET 使用Connection 对象来连接数据库,使用Command 或DataAdapter对象来执行SQL语句,并将执行的结果返回给DataReader 或 DataAdapter ,然后再使用取得的DataReader 或DataAdapter 对象操作数据结果。
DataAdapter:
主要是在数据源以及DataSet 之间执行数据传输的工作,它可以透过Command 对象下达命令后,并将取得的数据放入DataSet 对象中。这个对象是架构在Command对象上,并提供了许多配合DataSet 使用的功能。
DataSet: DataSet对象是ADO.NET的核心,基于DataSet的数据模型才使得ADO.NET实现离线式数据操作模型。可以把从数据库中所查询到的数据保留起来,甚至可以将整个数据库显示出来。DataSet 的能力不只是可以储存多个Table 而已,还可以透过DataAdapter对象取得一些例如主键等的数据表结构,并可以记录数据表间的关联。这个对象架构在DataAdapter对象上,本身不具备和数据源沟通的能力;也就是说我们是将DataAdapter对象当做DataSet 对象以及数据源间传输数据的桥梁。 DataSet是存在于内存中的数据库,是专门用来处理数据保存体中读出的数据。它的优点就是离线式的,一点读取到数据源中的数据后,就在内存中建立数据库的副本,在此之后的操作,直到执行更新命令为止,所有的操作都是在内存中完成的。不管底层的数据库是哪种形式,DataSet的行为都是一致。其中比较常用的列表控件(DataGridView,ComboBox)。
DataReader与DataAdapter和DataSet读取数据的区别
DataReader:
public static string strconn = "server=.;database=Test;uid=sa;pwd=123456";
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection(strconn);
conn.Open();
SqlCommand comm = new SqlCommand(); comm.Connection = conn;
comm.CommandText = "prcPageResult"; SqlParameter[] prams = {
new SqlParameter("@currPage", ""),
new SqlParameter("@showColumn", "*"),
new SqlParameter("@tabName", "test"),
new SqlParameter("@strCondition", ""),
new SqlParameter("@ascColumn", "ID"),
new SqlParameter("@bitOrderType", ""),
new SqlParameter("@pkColumn", "ID"),
new SqlParameter("@pageSize", "")
};
int j = ;
comm.Parameters.AddRange(prams);
comm.CommandType = CommandType.StoredProcedure;
List<testModel> entitylist = new List<testModel>();
using (SqlDataReader reader = comm.ExecuteReader())
{ while (reader.Read())
{
testModel entity = new testModel();
entity.ID = Convert.ToInt32(reader["ID"]);
entity.Name = reader["Name"].ToString();
entitylist.Add(entity);
}
}
for (int i = ; i < entitylist.Count; i++)
{
Console.WriteLine(entitylist[i].Name);
} conn.Close();
Console.Read(); }
DataAdapter和DataSet:
public static string strconn = "server=.;database=Test;uid=sa;pwd=123456";
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection(strconn);
conn.Open();
SqlCommand comm = new SqlCommand(); comm.Connection = conn;
comm.CommandText = "prcPageResult"; SqlParameter[] prams = {
new SqlParameter("@currPage", ""),
new SqlParameter("@showColumn", "*"),
new SqlParameter("@tabName", "test"),
new SqlParameter("@strCondition", ""),
new SqlParameter("@ascColumn", "ID"),
new SqlParameter("@bitOrderType", ""),
new SqlParameter("@pkColumn", "ID"),
new SqlParameter("@pageSize", "")
};
comm.Parameters.AddRange(prams);
comm.CommandType = CommandType.StoredProcedure; SqlDataAdapter da = new SqlDataAdapter(comm);
DataSet ds = new DataSet();
da.Fill(ds, "test");
List<testModel> entitylist = new List<testModel>(); foreach (DataRow item in ds.Tables[].Rows)
{
testModel entity = new testModel();
entity.ID = Convert.ToInt32(item["ID"]);
entity.Name = item["Name"].ToString() ;
entitylist.Add(entity);
}
conn.Close();
Console.Read(); }
SqlDataAdapter概述
SqlDataAdapter是 DataSet和 SQL Server之间的桥接器,用于检索和保存数据。SqlDataAdapter通过对数据源使用适当的Transact-SQL语句映射 Fill(它可更改DataSet中的数据以匹配数据源中的数据)和 Update(它可更改数据源中的数据以匹配 DataSet中的数据)来提供这一桥接。当SqlDataAdapter填充 DataSet时,它为返回的数据创建必需的表和列(如果这些表和列尚不存在)。
我们可以通过以下三种方法来创建SqlDataAdapter对象:
使用方法
1、通过连接字符串和查询语句
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
strSql="SELECT * FROM 表名";
SqlDataAdapter da=new SqlDataAdapter(strSql,strConn);
DataSet ds=new DataSet();//创建DataSet实例
da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令
这种方法有一个潜在的缺陷。假设应用程序中需要多个SqlDataAdapter对象,用这种方式来创建的话,会导致创建每个SqlDataAdapter时,都同时创建一个新的SqlConnection对象,方法二可以解决这个问题
2、通过查询语句和SqlConnection对象来创建
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
SqlConnection conn=new SqlConnection(strConn);
string strSql="SELECT * FROM 表名";
SqlDataAdapter da = new SqlDataAdapter(strSql, conn);
DataSet ds=new DataSet();//创建DataSet实例
da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令
3、通过SqlCommand对象来创建
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
SqlConnection connSql=new SqlConnection (strConn); //Sql链接类的实例化
connSql.Open ();//打开数据库
//使用SqlDataAdapter时没有必要从Connection.open()打开,
//SqlDataAdapter会自动打开关闭它。
string strSql = "SELECT * FROM 表名"; //要执行的SQL语句
SqlCommand cmd=new SqlCommand(strSql,connsql);
SqlDataAdapter da=new SqlDataAdapter(cmd); //创建DataAdapter数据适配器实例
DataSet ds=new DataSet();//创建DataSet实例
da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令
ConnSql.Close ();//关闭数据库
SqlDataAdapter da=new SqlDataAdapter(strSQL,ConnSql); //创建DataAdapter数据适配器实例DataSet ds=new DataSet();//创建DataSet实例da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令ConnSql.Close ();//关闭数据库
注意
如果只需要执行SQL语句或SP,就没必要用到DataAdapter ,直接用SqlCommand的Execute系列方法就可以了。sqlDataadapter的作用是实现Dataset和DB之间的桥梁:比如将对DataSet的修改更新到数据库。
SqlDataAdapter的UpdateCommand的执行机制是:当调用SqlDataAdapter.Update()时,检查DataSet中的所有行,然后对每一个修改过的Row执行SqlDataAdapter.UpdateCommand ,也就是说如果未修改DataSet中的数据,SqlDataAdapter.UpdateCommand不会执行。
使用要点
1、SqlDataAdapter内部通过SqlDataReader获取数据,而默认情况下SqlDataReader不能获知其查询语句对应的数据库表名,
所以下面的代码:
string strConn = "uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
strSql="SELECT * FROM 表名";
SqlDataAdapter da = new SqlDataAdapter(strSql,strConn);
DataSet ds = new DataSet();
da.Fill(ds);
会在DataSet中创建一个新的DataTable,这个新的DataTable会拥有名为CustomerID和CompanyName 列,但是DataTable对象的名称是Table,而不是我们希望的Customers。
这个问题,可以通过添加TableMapping来解决:
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
strSql="SELECT * FROM 表名";
SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);
da.TableMappings.Add("Table","Customers"); // 设置对象名称
DataSet ds=new DataSet();
da.Fill(ds);
其实最简洁的方法是通过使用Fill方法的重载,通过指定DataTable,像这样:
SqlDataAdapter.Fill(DataSet,"MyTableName");
这样就可以不必使用TableMappings集合。
2、在使用Fill方式时,可以指定DataTable,而不是DataSet:
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
strSql="SELECT * FROM 表名";
SqlDataAdapter da = new SqlDataAdapter(strSql, strConn);
DataTable tbl=new DataTable( );
da.Fill(tbl);
3、注意打开和关闭连接的处理
在调用SqlCommand对象执行sql命令之前,需要保证与该对象关联的SqlConnection对象时打开的,否则SqlCommand的方法执行时将引发一个异常,但是我们在上面的代码中看到,SqlDataAdapter没有这样的要求。
如果调用SqlDataAdapter的Fill方法,并且其SelectCommand属性的SqlConnection是关闭状态,则SqlDataAdapter会自动打开它,然后提交查询,获取结果,最后关闭连接。如果在调用Fill方法前,SqlConnection是打开的,则查询执行完毕后,SqlConnection还将是打开的,也就是说SqlDataAdapter会保证SqlConnection的状态恢复到原来的情形。
这有时会导致性能问题,需要注意,例如下面的代码:
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
SqlConnection conn=new SqlConnection(strConn);
SqlDataAdapter daCustomers,daOrders;
strSql="SELECT * FROM Customers";
daCustomers = new SqlDataAdapter(strSql, conn);
strSql="SELECT * FROM Orders";
daOrders=new SqlDataAdapter(strSql, conn);
DataSet ds=new DataSet();
daCustomers.Fill(ds,"Customers");
daOrders.Fill(ds,"Orders");
以上代码会导致连接被打开和关闭两次,在调用Fill方法时各一次。为了避免打开和关闭SqlConnection对象,在调用SqlDataAdapter对象的Fill方法之前,我们可以先打开SqlConnection对象,如果希望之后关闭连接,我们可以再调用Close方法,就像这样:
cn.Open();
daCustomers.Fill(ds,"Customers");
daOrders.Fill(ds,"Orders");
cn.Close();
4、多次调用Fill方法需要注意数据重复和有效更新数据的问题
string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串
strSql="SELECT * FROM Customers";
SqlDataAdapter da=new SqlDataAdapter(strSql, strConn);
DataSet ds=new DataSet();
da.Fill(ds,"Customers");
//…….
da.Fill(ds,"Customers");
我们分析上面的代码,通过两次调用Fill方法,SqlDataAdapter执行两次查询,并两次将查询结果保存到DataSet中,第一次调用在DataSet中创建了一个名为Customers的新表。第二次调用Fill方法将查询的结果追加到DataSet中的同一个表中,因此,每个客户的信息将在DataSet中出现两次!当然,如果数据库管理员对Customers表定义了主键,则SqlDataAdapter在天成DataTable时,会判断重复行,并自动丢弃掉旧的值。
考虑一下,假定一个特定客户在第一次调用Fill方法时,存储于数据库中,那么SqlDataAdapter会将其添加到新建的DataTable中。如果后来这个客户被删除了,那么第二次调用Fill方法时,SqlDataAdapter将不会在查询结果中找到该客户信息,但是它也不会将客户信息从DataSet中删除。这就导致了数据更新的问题。
所以推荐的做法是,在调用Fill方法前,先删除本地DataSet中缓存的数据!
转自:http://blog.csdn.net/chelen_jak/article/details/46821817
ADO种的增删改查
新增:
SqlConnection conn= new SqlConnection(connectionStr); //建立连接
conn.Open(); //打开数据库连接
string sqlStr = "(SQL执行语句,例如 insert into A values('abc',1))"; //定义相关的执行语句,相当于写好命令
SqlCommand command1 = new SqlCommand(sqlStr, conn); //构造函数指定命令对象所使用的连接对象connection1以及命令文本sqlStr ,相当于让系统接受命令。
command1.ExecuteNonQuery(); //ExecuteNonQuery()方法返回值受影响的记录条数为一整数,代表操作所影响到的行数,注意ExecuteNonQuery()方法一般用于执行 UPDATE、INSERT、DELETE等非查询语句 // UPDATE、INSERT、DELETE等非查询语句,可以理解为让系统执行命令
conn.Close(); ///关闭数据库连接
修改:
string connectionStr = "Data source=.;Initial Catalog=Student; Integrated Security=True";
SqlConnection connection = new SqlConnection(connectionStr);
string sqlStr = "update Course set Ccredit=5 where Cname='线性代数'";
SqlCommand command1= new SqlCommand(sqlStr, connection);
connection .Open();
if (command1.ExecuteNonQuery() > )
{
MessageBox.Show("学分修改成功!");
};
connection .Close();
删除:
string connectionStr = "Data source=.;Initial Catalog=Student; Integrated Security=True";
SqlConnection connection = new SqlConnection(connectionStr);
string sqlStr = "DELETE FROM Person WHERE LastName = 'Wilson' ";
SqlCommand command1= new SqlCommand(sqlStr, connection);
connection .Open(); if (command1.ExecuteNonQuery() > )
{
MessageBox.Show("删除成功!");
};
connection .Close();
ado.net中的 sqlconnection sqlcommand datareader dataset SqlDataAdapter之间的关系的更多相关文章
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- swift中,Optional、?与!之间的关系
swift中,Optional.?与!之间的关系 Optional <ClassName> 与 ClassName? 等价 对 ClassName! 强制取值会导致崩溃(如果对象为nil时 ...
- AE中网络分析的实现 的各个类之间的关系
原文AE中网络分析的实现 的各个类之间的关系 1. 创建网络数据集 在ArcCatalog中勾选网络分析模块,新建个人地理信息数据库—>新建要素数据集—>批量导入要素—>创建 ...
- jeecms系统使用介绍——jeecms中的内容、栏目、模型之间的关系
转载:https://blog.csdn.net/dongdong9223/article/details/76578120 jeecms是一款很不错的cms产品,之前在文章<基于Java的门户 ...
- 请解释ASP. NET中的web页面与隐藏类之间的关系
请解释ASP.NET中的web页面与其隐藏类之间的关系 其实页面与其隐藏类之间就是一个部分类的关系,你在页面上放一个一个的控件就是在这个类中定义一个一个的属性, 因为是同一个类的部分类的关系,所以隐藏 ...
- 全面解释java中StringBuilder、StringBuffer、String类之间的关系
StringBuilder.StringBuffer.String类之间的关系 java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,在上一篇博文中我 ...
- 程序中try、throw、catch三者之间的关系
c++程序中,采用一种专门的结构化处理逻辑的异常处理机制. 1.try语句 try语句块的作用是启动异常处理机制,检测try语句块中程序语句执行时可能出现的异常. try语句块总是与catch一同出现 ...
- 3.UML中的类图及类图之间的关系
统一建模语言简介 统一建模语言(Unified Modeling Language,UML)是用来设计软件蓝图的可视化建模语言,1997 年被国际对象管理组织(OMG)采纳为面向对象的建模语言的国际标 ...
- GOF 的23种JAVA常用设计模式总结 02 UML中的类图与类图之间的关系
统一建模语言UML 统一建模语言(Unified Modeling Language,UML)是用来设计软件蓝图的可视化建模语言,1997 年被国际对象管理组织(OMG)采纳为面向对象的建模语言的国际 ...
随机推荐
- Enabling Remote Errors in SSRS
January 18, 2011 By default the remote errors property in SQL Server Reporting Services is set to fa ...
- 微信小程序开发中的二三事之网易云信IMSDK DEMO
本文由作者邹永胜授权网易云社区发布. 简介 为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程.用产品的话说就是: 云信 IM 小程序 SDK 的能力 ...
- 「ZJOI 2010」 排列计数
题目链接 戳我 \(Solution\) 其实我们可以发现这题等价于让你求: 用\(1\)~\(n\)的数组成一个完全二叉树使之满足小根堆性质的方案数 于是我们可以考虑\(dp\) 假设我们现在在\( ...
- 自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 (转载)
自动统计安卓log中Anr,Crash,Singnal出现数量的Python脚本 转自:https://www.cnblogs.com/ailiailan/p/8304989.html 作为测试, ...
- JMeter组件之BeanShell PostProcessor的使用
1. 场景一:获取请求响应中的数据,并保存 import com.alibaba.fastjson.*; // 引入包.这个包需要先放在:<安装目录>\apache-jmeter-3.2 ...
- python --爬虫--爬取百度翻译
import requestsimport json class baidufanyi: def __init__(self, trans_str): self.lang_detect_url = ' ...
- 机器学习笔记(四)--sklearn数据集
sklearn数据集 (一)机器学习的一般数据集会划分为两个部分 训练数据:用于训练,构建模型. 测试数据:在模型检验时使用,用于评估模型是否有效. 划分数据的API:sklearn.model_se ...
- PHP中引入文件的四种方式详解
四种语句 PHP中有四个加载文件的语句:include.require.include_once.require_once. 基本语法 require:require函数一般放在PHP脚本的最前面,P ...
- iOS 本地时间 / UTC时间 / 时间戳等操作 / 获取当前年月日
//获得当前时间并且转为字符串 - (NSString *)dateTransformToTimeString { NSDate *currentDate = [NSDate date];//获得当前 ...
- 社区发现SLPA算法
社区(community)定义:同一社区内的节点与节点之间关系紧密,而社区与社区之间的关系稀疏. 设图G=G(V,E),所谓社区发现是指在图G中确定nc(>=1)个社区C={C1,C2,..., ...