C#中SqlDataAdapter的使用小结

简介:

SqlDataAdapter概述

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

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

使用方法

 

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

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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命令  
 

这种方法有一个潜在的缺陷。假设应用程序中需要多个SqlDataAdapter对象,用这种方式来创建的话,会导致创建每个SqlDataAdapter时,都同时创建一个新的SqlConnection对象,方法二可以解决这个问题

 

2、通过查询语句和SqlConnection对象来创建

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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命令  

 

3、通过SqlCommand对象来创建

 

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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 ();//关闭数据库   


SqlDataAdapter da=new SqlDataAdapter(strSQL,ConnSql); //创建DataAdapter数据适配器实例DataSet ds=new DataSet();//创建DataSet实例da.Fill(ds,"自定义虚拟表名");//使用DataAdapter的Fill方法(填充),调用SELECT命令ConnSql.Close ();//关闭数据库

注意

 

如果只需要执行SQL语句或SP,就没必要用到DataAdapter ,直接用SqlCommandExecute系列方法就可以了。sqlDataadapter的作用是实现DatasetDB之间的桥梁:比如将对DataSet的修改更新到数据库

SqlDataAdapterUpdateCommand的执行机制是:当调用SqlDataAdapter.Update()时,检查DataSet中的所有行,然后对每一个修改过的Row执行SqlDataAdapter.UpdateCommand ,也就是说如果未修改DataSet中的数据,SqlDataAdapter.UpdateCommand不会执行。

使用要点

1、SqlDataAdapter内部通过SqlDataReader获取数据,而默认情况下SqlDataReader不能获知其查询语句对应的数据库表名,

所以下面的代码:

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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);  

 

会在DataSet中创建一个新的DataTable,这个新的DataTable会拥有名为CustomerIDCompanyName 列,但是DataTable对象的名称是Table,而不是我们希望的Customers

 

这个问题,可以通过添加TableMapping来解决: 

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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);  
其实最简洁的方法是通过使用 Fill 方法的重载,通过指定 DataTable ,像这样:

SqlDataAdapter.Fill(DataSet,"MyTableName");

这样就可以不必使用TableMappings集合。

 

2、在使用Fill方式时,可以指定DataTable,而不是DataSet

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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);  

3、注意打开和关闭连接的处理

 

在调用SqlCommand对象执行sql命令之前,需要保证与该对象关联的SqlConnection对象时打开的,否则SqlCommand的方法执行时将引发一个异常,但是我们在上面的代码中看到,SqlDataAdapter没有这样的要求。

 

如果调用SqlDataAdapterFill方法,并且其SelectCommand属性的SqlConnection是关闭状态,则SqlDataAdapter会自动打开它,然后提交查询,获取结果,最后关闭连接。如果在调用Fill方法前,SqlConnection是打开的,则查询执行完毕后,SqlConnection还将是打开的,也就是说SqlDataAdapter会保证SqlConnection的状态恢复到原来的情形。

 

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

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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");  


 

以上代码会导致连接被打开和关闭两次,在调用Fill方法时各一次。为了避免打开和关闭SqlConnection对象,在调用SqlDataAdapter对象的Fill方法之前,我们可以先打开SqlConnection对象,如果希望之后关闭连接,我们可以再调用Close方法,就像这样:

 

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. cn.Open();  
  2.    
  3. daCustomers.Fill(ds,"Customers");  
  4.  daOrders.Fill(ds,"Orders");  
  5.    
  6. cn.Close();  


 

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

 

[csharp] view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  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");  


 

我们分析上面的代码,通过两次调用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

目录
相关文章
|
机器学习/深度学习 监控 算法
图像去雾综述
图像去雾综述
|
Java C# 开发者
【干货】Java开发者快速上手.NET指南
【干货】Java开发者快速上手.NET指南
306 1
|
存储 数据采集 监控
数据标准码表的3种创建方式
码表(Lookup表)由可枚举数据组成,用于存储名称与编码的映射关系,适用于属性值约束和质量监控。本文介绍在Dataphin创建码表的三种方式:1) 引用内置模板库,如行政区划、度量单位等标准码表;2) 从已有维表逆向生成码表,实现数据资产复用;3) 自定义创建,支持在线编辑或本地导入。通过这些方式,用户可高效管理码表,提升数据标准化水平,并将其应用于数据标准和质量规则中,确保数据一致性和合规性。
692 3
|
机器学习/深度学习 存储 缓存
DeepSeek × 时间序列 :DeepSeek-TS,基于状态空间增强MLA与GRPO的时序预测新框架
DeepSeek-TS 是一种创新的多产品时间序列预测框架,结合了 DeepSeek 中高效的多头潜在注意力(MLA)和群组相对策略优化(GRPO)技术。该框架通过扩展 MLA 提出 MLA-Mamba,允许潜在特征通过非线性激活的状态空间模型动态演变,提供自适应记忆以适应趋势变化。同时,通过 GRPO 引入智能决策过程,持续改进预测,有效响应销售模式的突变。实验结果显示,DeepSeek-TS 在建模复杂的产品间关系和适应非线性动态方面表现出色,显著优于经典的 ARMA 模型和标准的基于 GRU 的网络。
1865 9
DeepSeek × 时间序列 :DeepSeek-TS,基于状态空间增强MLA与GRPO的时序预测新框架
|
存储 算法 关系型数据库
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
NoSQL 算法 Java
使用 Spring Boot 实现限流功能:从理论到实践
【6月更文挑战第18天】在微服务和高并发系统中,限流(Rate Limiting)是一种非常重要的技术手段,用于保护系统免受过载,确保服务的稳定性。限流可以控制请求的速率,防止单个客户端或恶意用户消耗过多的资源,从而影响其他用户。
2215 5
|
JavaScript 前端开发 物联网
Node.js一般在什么场景下使用?
Node.js是一个基于Chrome V8 JavaScript引擎构建的开源运行时环境,它允许开发者使用JavaScript在服务器端运行代码。Node.js具有高性能、轻量级、事件驱动和非阻塞I/O等特性,这些特性使得它在多种场景下具有广泛的应用。
593 0
|
监控 Linux
在Linux中,如何实时查看网卡流量为多少?如何查看历史网卡流量?
在Linux中,如何实时查看网卡流量为多少?如何查看历史网卡流量?
|
Dubbo Java 应用服务中间件
如何在 Spring Boot 中制作和管理 Banner:完全指南
在 Spring Boot 应用的初启页面展示独特的ASCII艺术品能够为您的应用增添特色,并为用户或开发者提供温馨的问候。这种ASCII图案常常蕴含着项目的名称、版本信息、以及作者等重要数据。除此之外,这样的欢迎页面还起到加强品牌形象的作用。

热门文章

最新文章