知识大全 ADO.NET实用经验与大家分享
Posted 属性
篇首语:生活是活给自己看的,你有多大成色,世界才会给你多大脸色。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 ADO.NET实用经验与大家分享相关的知识,希望对你有一定的参考价值。
ADO.NET实用经验与大家分享 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
ADO NET作为微软最新的数据访问技术 已经在企业开发中得到了广泛的应用 对于一线的开发人员来说 掌握基本的概念和技术之后 提高应用水平和解决实际问题的最有效手段 莫过于相互交流彼此的最佳时间经验经验 在这篇文章中 两位ADO NET专家向读者毫无保留地 详尽地介绍了很多实用经验
简介
本文为您提供了在Microsoft ADO NET应用程序中实现和获得最佳性能 可伸缩性以及功能的最佳解决方案 同时也讲述了使用ADO NET中可用对象的最佳实践 并提出一些有助于优化ADO NET应用程序设计的建议
NET框架数据提供程序
NET框架中的数据提供程序(Data Provider)在应用程序和数据源之间起到桥梁作用……NET框架数据提供程序能够从数据源中返回查询结果 对数据源执行命令 将DataSet中的更改传播给数据源 本文包括有关哪个 NET框架数据提供程序是最适合您需要的一些技巧
使用哪个 NET框架数据提供程序?
为了使您的应用程序获得最佳性能 请使用最适合您的数据源的 NET框架数据提供程序 有许多数据提供程序可供您的应用程序选用
连接到SQL Server 或更高版本
为了在连接到Microsoft SQL Server 或更高版本时获得最佳性能 请使用SQL Server NET数据提供程序 SQL Server NET数据提供程序的设计目的就在于不通过任何附加技术层就可以直接访问SQL Server
连接到ODBC数据源
ODBC NET数据提供程序可在Microsoft Data ODBC命名空间中找到 它的体系结构与用于SQL Server和OLE DB的 NET数据提供程序相同 ODBC NET数据提供程序遵循命名约定 以 ODBC 为前缀(例如 OdbcConnection) 并使用标准ODBC连接字符串
使用DataReader DataSet DataAdapter和DataView
ADO NET提供以下两个对象 用于检索关系数据并将其存储在内存中 DataSet和DataReader DataSet提供一个内存中数据的关系表示形式 一整套包括一些表在内的数据(这些表包含数据 对数据进行排序并约束数据) 以及表之间的关系 DataReader提供一个来自数据库的快速 仅向前 只读数据流
当使用DataSet时 经常会利用DataAdapter(也可能是CommandBuilder)与数据源进行交互 当使用DataSet时 也可以利用DataView对DataSet中的数据应用排序和筛选 也可以从DataSet继承 创建强类型DataSet 用于将表 行和列作为强类型对象属性公开
下列主题包括的信息涉及 使用DataSet或DataReader的最佳时机 如何优化访问它们所包含数据 以及如何优化使用DataAdapter(包括CommandBuilder)和DataView的技巧
DataSet与DataReader
当设计应用程序时 要考虑应用程序所需功能的等级 以确定使用DataSet或者是DataReader
要通过应用程序执行以下操作 就要使用DataSet
) 在结果的多个离散表之间进行导航
) 操作来自多个数据源(例如 来自多个数据库 一个XML文件和一个电子表格的混合数据)的数据
) 在各层之间交换数据或使用XML Web服务 与DataReader不同的是 DataSet能传递给远程客户端
) 重用同样的记录集合 以便通过缓存获得性能改善(例如排序 搜索或筛选数据)
) 每条记录都需要执行大量处理 对使用DataReader返回的每一行进行扩展处理会延长服务于DataReader的连接的必要时间 这影响了性能
) 使用XML操作对数据进行操作 例如可扩展样式表语言转换(XSLT转换)或XPath查询
对于下列情况 要在应用程序中使用DataReader
) 不需要缓存数据
) 要处理的结果集太大 内存中放不下
) 一旦需要以仅向前 只读方式快速访问数据
注填充DataSet时 DataAdapter使用DataReader 因此 使用DataAdapter取代DataSet提升的性能表现为节省了DataSet占用内存和填充DataSet需要的循环 一般来说 此性能提升只是象征性的 因此 设计决策应以所需功能为基础
使用强类型DataSet的好处
DataSet的另一个好处是可被继承以创建一个强类型DataSet 强类型DataSet的好处包括设计时类型检查 以及Microsoft Visual Studio NET用于强类型DataSet语句结束所带来的好处 修改了DataSet的架构或关系结构后 就可以创建一个强类型DataSet 将行和列作为对象的属性公开 而不是作为集合中的项公开 例如 不公开客户表中行的姓名列 而公开Customer对象的Name属性 类型化DataSet从DataSet类派生 因此不会牺牲DataSet的任何功能 也就是说 类型化DataSet仍能远程访问 并作为数据绑定控件(例如DataGrid)的数据源提供 如果架构事先不可知 仍能受益于通用DataSet的功能 但却不能受益于强类型DataSet的附加功能
处理强类型DataSet中的空引用
使用强类型DataSet时 可以使用DataSet的XML架构定义语言(XSD)架构来确保强类型DataSet可以正确处理空引用 nullValue标识符使您可用一个指定的值String Empty代替DBNull 保留空引用或引发异常 选择哪个选项取决于应用程序的上下文 默认情况下 如果遇到空引用 就会引发异常
刷新DataSet中的数据
如果想用服务器上的更新值刷新DataSet中的值 就使用DataAdapter Fill 如果有在DataTable上定义的主键 DataAdapter Fill会根据主键进行新行匹配 并且当更改到现有行时应用服务器上的值 即使刷新之前修改了这些数据 刷新行的RowState仍被设置为Unchanged 注意 如果没有为DataTable定义主键 DataAdapter Fill就用可能重复的主键值添加新行
如果想用来自服务器的当前值刷新表 并同时保留对表中的行所做的任何更改 必须首先用DataAdapter Fill填充表 并填充一个新的DataTable 然后用preserveChanges值true将DataTable合并到DataSet之中
在DataSet中搜索数据
在DataSet中查询与特定条件相匹配的行时 可以利用基于索引的查找提高搜索性能 当将PrimaryKey值赋给DataTable时 会创建一个索引 当给DataTable创建DataView时 也会创建一个索引 下面是一些利用基于索引进行查找的技巧
) 如果对组成DataTable的PrimaryKey的列进行查询 要使用DataTable Rows Find而不是DataTable Select
) 对于涉及到非主键列的查询 可以使用DataView为数据的多个查询提高性能 当将排序顺序应用到DataView时 就会建立一个搜索时使用的索引 DataView公开Find和FindRows方法 以便查询基础DataTable中的数据
) 如果不需要表的排序视图 仍可以通过为DataTable创建DataView来利用基于索引的查找 注意 只有对数据执行多个查询操作时 这样才会带来好处 如果只执行单一查询 创建索引所需要的处理就会降低使用索引所带来的性能提升
DataView构造
如果创建了DataView 并且修改了Sort RowFilter或RowStateFilter属性 DataView就会为基础DataTable中的数据建立索引 创建DataView对象时 要使用DataView构造函数 它用Sort RowFilter和RowStateFilter值作为构造函数参数(与基础DataTable一起) 结果是创建了一次索引 创建一个 空 DataView并随后设置Sort RowFilter或RowStateFilter属性 会导致索引至少创建两次
分页
ADO NET可以显式控制从数据源中返回什么样的数据 以及在DataSet中本地缓存多少数据 对查询结果的分页没有唯一的答案 但下面有一些设计应用程序时应该考虑的技巧
) 避免使用带有startRecord和maxRecords值的DataAdapter Fill重载 当以这种方式填充DataSet时 只有maxRecords参数(从startRecord参数标识的记录开始)指定的记录数量用于填充DataSet 但无论如何总是返回完整的查询 这就会引起不必要的处理 用于读取 不需要的 记录 而且为了返回附加记录 会耗尽不必要的服务器资源
) 用于每次只返回一页记录的技术是创建SQL语句 将WHERE子句以及ORDER BY子句和TOP谓词组合起来 此技术取决于存在一种可唯一标识每一行的办法 当浏览下一页记录时 修改WHERE子句使之包含所有唯一标识符大于当前页最后一个唯一标识符的记录 当浏览上一页记录时 修改WHERE子句使之返回所有唯一标识符小于当前页第一个唯一标识符的记录 两种查询都只返回记录的TOP页 当浏览上一页时 需要以降序为结果排序 这将有效地返回查询的最后一页(如果需要 显示之前也许要重新排序结果)
) 另一项每次只返回一页记录的技术是创建SQL语句 将TOP谓词和嵌入式SELECT语句的使用结合在一起 此技术并不依赖于存在一种可唯一标识每一行的办法 使用这项技术的第一步是将所需页的数量与页大小相乘 然后将结果传递给SQL Query的TOP谓词 该查询以升序排列 再将此查询嵌入到另一个查询中 后者从降序排列的嵌入式查询结果中选择TOP页大小 实质上 返回的是嵌入式查询的最后一页 例如 要返回查询结果的第三页(页大小是 ) 应该书写如下所示的命令
SELECT TOP * FROM (SELECT TOP * FROM Customers ORDER BY Id ASC) AS Table ORDER BY Id DESC
注意 从查询中返回的结果页以降序显示 如果需要 应该重新排序
) 如果数据不经常变动 可以在DataSet中本地维护一个记录缓存 以此提高性能 例如 可以在本地DataSet中存储 页有用的数据 并且只有当用户浏览超出缓存第一页和最后一页时 才从数据源中查询新数据
用架构填充DataSet
当用数据填充DataSet时 DataAdapter Fill方法使用DataSet的现有架构 并使用从SelectCommand返回的数据填充它 如果在DataSet中没有表名与要被填充的表名相匹配 Fill方法就会创建一个表 默认情况下 Fill仅定义列和列类型
通过设置DataAdapter的MissingSchemaAction属性 可以重写Fill的默认行为 例如 要让Fill创建一个表架构 并且还包括主键信息 唯一约束 列属性 是否允许为空 最大列长度 只读列和自动增量的列 就要将DataAdapter MissingSchemaAction指定为MissingSchemaAction AddWithKey 或者 在调用DataAdapter Fill前 可以调用DataAdapter FillSchema来确保当填充DataSet时架构已到位
对FillSchema的调用会产生一个到服务器的额外行程 用于检索附加架构信息 为了获得最佳性能 需要在调用Fill之前指定DataSet的架构 或者设置DataAdapter的MissingSchemaAction
使用CommandBuilder的最佳实践
假设SelectCommand执行单一表SELECT CommandBuilder就会以DataAdapter的SelectCommand属性为基础自动生成DataAdapter的InsertCommand UpdateCommand 和DeleteCommand属性 下面是为获得最佳性能而使用CommandBuilder的一些技巧
) CommandBuilder的使用应该限制在设计时或即席方案中 生成DataAdapter命令属性所必需的处理会影响性能 如果预先知道INSERT/UPDATE/DELETE语句的内容 就显式设置它们 一个比较好的设计技巧是 为INSERT/UPDATE/DELETE命令创建存储过程并显式配置DataAdapter命令属性以使用它们
) CommandBuilder使用DataAdapter的SelectCommand属性确定其他命令属性的值 如果DataAdapter的SelectCommand本身曾经更改过 确保调用RefreshSchema以更新命令属性
) 如果DataAdapter命令属性为空(命令属性默认情况下为空) CommandBuilder仅仅为它生成一条命令 如果显式设置了命令属性 CommandBuilder不会重写它 如果希望CommandBuilder为以前已经设置过的命令属性生成命令 就将命令属性设置为空
批处理SQL语句
很多数据库支持将多条命令合并或批处理成一条单一命令执行 例如 SQL Server使您可以用分号 分隔命令 将多条命令合并成单一命令 能减少到服务器的行程数 并提高应用程序的性能 例如 可以将所有预定的删除在应用程序中本地存储起来 然后再发出一条批处理命令调用 从数据源删除它们
虽然这样做确实能提高性能 但是 当对DataSet中的数据更新进行管理时 可能会增加应用程序的复杂性 要保持简单 可能要在DataSet中为每个DataTable创建一个DataAdapter
用多个表填充DataSet
如果使用批处理SQL语句检索多个表并填充DataSet 第一个表用指定给Fill方法的表名命名 后面的表用指定给Fill方法的表名加上一个从 开始并且增量为 的数字命名 例如 如果运行下面的代码
Visual Basic Dim da As SqlDataAdapter = New SqlDataAdapter( SELECT * FROM Customers SELECT * FROM Orders myConnection) Dim ds As DataSet = New DataSet() da Fill(ds Customers ) //C# SqlDataAdapter da = new SqlDataAdapter( SELECT * FROM Customers SELECT * FROM Orders myConnection) DataSet ds = new DataSet() da Fill(ds Customers )
来自Customers表的数据放在名为 Customers 的DataTable中 来自Orders表的数据放在名为 Customers 的DataTable中
填充完DataSet之后 可以很容易地将 Customers 表的TableName属性改为 Orders 但是 后面的填充会导致 Customers 表被重新填充 而 Orders 表会被忽略 并创建另外一个 Customers 表 为了对这种情况作出补救 创建一个DataTableMapping 将 Customers 映射到 Orders 并为其他后面的表创建其他的表映射 例如
Visual Basic Dim da As SqlDataAdapter = New SqlDataAdapter( SELECT * FROM Customers SELECT * FROM Orders myConnection) da TableMappings Add( Customers Orders ) Dim ds As DataSet = New DataSet() da Fill(ds Customers ) //C# SqlDataAdapter da = new SqlDataAdapter( SELECT * FROM Customers SELECT * FROM Orders myConnection) da TableMappings Add( Customers Orders ) DataSet ds = new DataSet() da Fill(ds Customers )
使用DataReader
下面是一些使用DataReader获得最佳性能的技巧 同时还回答了一些关于使用DataReader的常见问题
) 在访问相关Command的任何输出参数之前 必须关闭DataReader
) 完成读数据之后总是要关闭DataReader 如果使用Connection只是用于返回DataReader 那么关闭DataReader之后立刻关闭它
另外一个显式关闭Connection的方法是将CommandBehavior CloseConnection传递给ExecuteReader方法 以确保相关的连接在关闭DataReader时被关闭 如果从一个方法返回DataReader 而且不能控制DataReader或相关连接的关闭 则这样做特别有用
) 不能在层之间远程访问DataReader DataReader是为已连接好的数据访问设计的
) 当访问列数据时 使用类型化访问器 例如 GetString GetInt 等 这使您不用进行将GetValue返回的Object强制转换成特定类型所需的处理
) 一个单一连接每次只能打开一个DataReader 在ADO中 如果打开一个单一连接 并且请求两个使用只进 只读游标的记录集 那么ADO会在游标生存期内隐式打开第二个 未池化的到数据存储区的连接 然后再隐式关闭该连接 对于ADO NET 秘密 完成的动作很少 如果想在相同的数据存储区上同时打开两个DataReaders 就必须显式创建两个连接 每个DataReader一个 这是ADO NET为池化连接的使用提供更多控制的一种方法
) 默认情况下 DataReader每次Read时都要将整行加载到内存 这允许在当前行内随机访问列 如果不需要这种随机访问 为了提高性能 就将CommandBehavior SequentialAccess传递给ExecuteReader调用 这将DataReader的默认行为更改为仅在请求时将数据加载到内存 注意 CommandBehavior SequentialAccess要求顺序访问返回的列 也就是说 一旦读过返回的列 就不能再读它的值了
) 如果已经完成读取来自DataReader的数据 但仍然有大量挂起的未读结果 就在调用DataReader的Close之前先调用Command的Cancel 调用DataReader的Close会导致在关闭游标之前检索挂起的结果并清空流 调用Command的Cancel会放弃服务器上的结果 这样 DataReader在关闭的时候就不必读这些结果 如果要从Command返回输出参数 还要调用Cancel放弃它们 如果需要读取任何输出参数 不要调用Command的Cancel 只要调用DataReader的Close即可
二进制大对象(BLOB)
用DataReader检索二进制大对象(BLOB)时 应该将CommandBehavior SequentialAccess传递给ExecuteReader方法调用 因为DataReader的默认行为是每次Read都将整行加载到内存 又因为BLOB值可能非常大 所以结果可能由于单个BLOB而使大量内存被用光 SequentialAccess将DataReader的行为设置为只加载请求的数据 然后还可以使用GetBytes或GetChars控制每次加载多少数据
cha138/Article/program/net/201311/12789相关参考
ADO.NET实用技巧两则 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 要想充分发挥ADONE
处理ADO与ADO.NET对比介绍 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! ADONET统
ADO.Net与ADO在数据内存中的差异讨论 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 数据
数据访问与ADO.NET 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!ADONET的设计目标 A
ADO.NET的并行控制与数据存取冲突侦测 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 
对于防范"电信诈骗",您有哪些经验可以与大家分享 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!对于
ADO.NET和ADO的比较 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
总起:我并不是一个什么求职牛人,也没有拿到多少OFFER,主要原因是我群殴比较烂,殴了10来场了,没过几场。所以在求职过程中,别的方面我不敢多言,但是在笔试方面,还是有一些心得的,现与大家分享与此,也
在ADO和ADO.NET中管理离线数据 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 您可以使用
ADO.NET入门(4) 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 转换现有代码 &nbs