C#中SqlDataAdapter的使用小结

SqlDataAdapter概述

SqlDataAdapter是 DataSet和 SQL Server之间的桥接器,用于检索和保存数据。SqlDataAdapter通过对数据源使用适当的Transact-SQL语句映射 Fill(它可更改DataSet中的数据以匹配数据源中的数据)和 Update(它可更改数据源中的数据以匹配 DataSet中的数据)来提供这一桥接。当SqlDataAdapter填充 DataSet时,它为返回的数据创建必需的表和列(如果这些表和列尚不存在)。

)我们可以通过以下三种方法来创建SqlDataAdapter对象:

使用方法

 

1、通过连接字符串和查询语句 

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串  
  2. strSql="SELECT * FROM 表名";  
  3.    
  4. SqlDataAdapter da=new SqlDataAdapter(strSql,strConn);  
  5. DataSet ds=new DataSet();//创建DataSet实例  
  6. da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令  
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对象来创建

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串  
  2.  SqlConnection conn=new SqlConnection(strConn);  
  3.    
  4. string strSql="SELECT * FROM 表名";  
  5.  SqlDataAdapter da = new SqlDataAdapter(strSql, conn);  
  6. DataSet ds=new DataSet();//创建DataSet实例  
  7. da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令  
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对象来创建

 

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  2. SqlConnection connSql=new SqlConnection (strConn); //Sql链接类的实例化    
  3. connSql.Open ();//打开数据库    
  4. //使用SqlDataAdapter时没有必要从Connection.open()打开,    
  5. //SqlDataAdapter会自动打开关闭它。    
  6. string strSql = "SELECT * FROM 表名"; //要执行的SQL语句    
  7. SqlCommand cmd=new SqlCommand(strSql,connsql);  
  8. SqlDataAdapter da=new SqlDataAdapter(cmd); //创建DataAdapter数据适配器实例    
  9. DataSet ds=new DataSet();//创建DataSet实例    
  10. da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令    
  11. ConnSql.Close ();//关闭数据库   
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不能获知其查询语句对应的数据库表名,

所以下面的代码:

[csharp] view plain copy print?

  1. string strConn = "uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  2. strSql="SELECT * FROM 表名";    
  3.    
  4. SqlDataAdapter da = new SqlDataAdapter(strSql,strConn);  
  5. DataSet ds = new DataSet();  
  6. da.Fill(ds);  
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来解决: 

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  2. strSql="SELECT * FROM 表名";    
  3.    
  4. SqlDataAdapter da=new SqlDataAdapter(strSQL,strConn);  
  5. da.TableMappings.Add("Table","Customers");   // 设置对象名称  
  6. DataSet ds=new DataSet();  
  7. da.Fill(ds);  
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:

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  2. strSql="SELECT * FROM 表名";    
  3.    
  4. SqlDataAdapter da = new SqlDataAdapter(strSql, strConn);  
  5. DataTable tbl=new DataTable( );  
  6. da.Fill(tbl);  
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的状态恢复到原来的情形。

 

这有时会导致性能问题,需要注意,例如下面的代码:

[csharp] view plain copy print?

  1.    
  2. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  3. SqlConnection conn=new SqlConnection(strConn);  
  4. SqlDataAdapter daCustomers,daOrders;  
  5.    
  6. strSql="SELECT * FROM Customers";  
  7.  daCustomers = new SqlDataAdapter(strSql, conn);  
  8.    
  9. strSql="SELECT * FROM Orders";  
  10.  daOrders=new SqlDataAdapter(strSql, conn);  
  11.    
  12. DataSet ds=new DataSet();  
  13.    
  14. daCustomers.Fill(ds,"Customers");  
  15.  daOrders.Fill(ds,"Orders");  
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方法,就像这样:

 

[csharp] view plain copy print?

  1. cn.Open();  
  2.    
  3. daCustomers.Fill(ds,"Customers");  
  4.  daOrders.Fill(ds,"Orders");  
  5.    
  6. cn.Close();  
cn.Open();

daCustomers.Fill(ds,"Customers");
 daOrders.Fill(ds,"Orders");

cn.Close();

 

4、多次调用Fill方法需要注意数据重复和有效更新数据的问题

 

[csharp] view plain copy print?

  1. string strConn="uid=账号;pwd=密码;database=数据库;server=服务器";//SQL Server链接字符串    
  2.  strSql="SELECT * FROM Customers";  
  3.    
  4. SqlDataAdapter da=new SqlDataAdapter(strSql, strConn);  
  5.  DataSet ds=new DataSet();  
  6.  da.Fill(ds,"Customers");  
  7.    
  8. //…….  
  9.    
  10. da.Fill(ds,"Customers");  
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/gatieme/article/details/20695853

时间: 2024-09-12 00:32:49

C#中SqlDataAdapter的使用小结的相关文章

ECMAScript5(ES5)中bind方法使用小结

  这篇文章主要介绍了ECMAScript5(ES5)中bind方法使用小结,bind和call以及apply一样,都是可以改变上下文的this指向的,需要的朋友可以参考下 一直以来对和this有关的东西模糊不清,譬如call.apply等等.这次看到一个和bind有关的笔试题,故记此文以备忘. bind和call以及apply一样,都是可以改变上下文的this指向的.不同的是,call和apply一样,直接引用在方法上,而bind绑定this后返回一个方法,但内部核心还是apply. 直接看例

Shell中的变量使用小结

  这篇文章主要介绍了Shell中的变量使用小结,本文总结了变量的语法.常见使用形式等内容,并分别给出代码示例,需要的朋友可以参考下 变量的定义,只能以字母和下划线开始,区分大小写,可以包含数字 字母下划线.详见官方手册    代码如下: [root@svn shell_example]# yourname='Linux' [root@svn shell_example]# echo $yourname Linux [root@svn shell_example]# YourName="linu

Java中getResourceAsStream的用法小结

Java中getResourceAsStream的用法小结 一.Java中的getResourceAsStream主要有以下三种用法:1.Class.getResourceAsStream(String path)      path 不以'/'开头时默认是从此类所在的包下取资源,以'/'开头则是从ClassPath根下获取.     其实是通过path构造一个绝对路径,最终还是由ClassLoader获取资源. 2.Class.getClassLoader.getResourceAsStrea

vim中执行shell命令小结

vim中执行shell命令,有以下几种形式 1):!command 不退出vim,并执行shell命令command,将命令输出显示在vim的命令区域,不会改变当前编辑的文件的内容 例如 :!ls -l   特别的可以运行:!bash来启动一个bash shell并执行命令,不需要退出vim 2):r !command 将shell命令command的结果插入到当前行的下一行 例如 :r !date,读取系统时间并插入到当前行的下一行. 3):起始行号,结束行号 !command 将起始行号和结

Linux c中define的用法小结_C 语言

define的用法只是一种纯粹的替换功能,宏定义的替换是预处理器处理的替换. 一:简单的宏定义用法 格式:#define 标识符 替换内容 替换的内容可以是数字,字符,字符串,特殊字符和空格,后面是什么内容就会替换成什么内容. 例如: #define  N   5 效果等同于 int  array [5]; int  array[N]; 同样效果: #define N = 5 int array[N];    效果等同于 int  array[= 5]; 同样效果: #define N   5;

Java中的字符串用法小结_java

本文实例总结了Java中的字符串用法.分享给大家供大家参考.具体分析如下: 字符串的本质是char类型的数组,但在java中,所有用双引号""声明的字符串都是一个String类的对象.这也正体现了Java完全面向对象的语言特点. String 类 1.String类对象表示的是一个常量字符串.它是不可变长度的.也就是说,一旦创建了一个String类的实例,那么这个实例所表示的串是不可改变的.类似于 str = str + "Hello"; 这样的操作,实质上是将 s

Java中String.split()用法小结_java

在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1.如果用"."作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split("."); 2.如果用"|"作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.s

JavaScript中的时间处理小结_javascript技巧

废话不多说了,主要通过以下七个方面给大家总结了时间处理相关知识. 1.获取当前时间 function getNowTime() { return new Date(); } 2.时间与天数相加 function getTimeAddDays(time, days) { return new Date(time.getTime() + days * 24 * 60 * 60 * 1000); } 3.获取并格式化日期:年-月-日 function getFormatDate(time) { ret

jquery 插件开发 extjs中的extend用法小结_jquery

在jquery中,extend其实在做插件时还是用的比较多的,今天同时小结jquery和ext js中 的extend用法,先来看jquery中的. 1) extend(dest,src1,src2,src3...); 复制代码 代码如下: var start = { id: 123, count: 41, desc: 'this is information', title: 'Base Object', tag: 'uncategorized', values: [1,1,2,3,5,8,1