ADO.NET 最佳实践






3.17/5 (16投票s)
本文包含一些在使用 ADO.NET 时可以考虑的技巧。
引言
这里有一些在使用 ADO.NET 时可以考虑的技巧。这些技巧有助于有效使用 ADO.NET。
1. 数据库连接
在使用数据库时,应尽可能晚地打开连接,并尽可能早地关闭连接。
始终最好使用数据库连接池。当应用程序使用连接池时,一个已创建的连接会返回到连接池中,并可以被系统重新用于另一个数据库调用。通过使用连接池中的连接,可以绕过创建连接的开销。连接池大小可以在连接字符串中定义。对于相同的连接字符串,ADO.NET 会使用相同的连接池。
您应该始终调用连接对象的 Close 方法。调用 Close 方法会将连接返回到连接池。然后,来自连接池的这个连接就可以被重新使用。您不应该依赖垃圾回收器来销毁连接对象。
最好使用 C# 的“using
”块来处理连接。由于连接对象实现了 IDisposable
接口,这会自动处理连接的释放。
2. 事务
大多数企业级分布式应用程序都使用事务。有两种事务:手动事务和自动事务。事务可以跨越一个数据库或多个数据库。在 ADO.NET 中,我们可以通过调用连接对象的 BeginTransaction
方法来使用事务。自动事务的使用可能会对性能造成开销。
3. 连接字符串
建议安全地存储连接字符串,因为它是一个非常敏感的信息。不建议以明文形式存储连接字符串。连接字符串应该被加密。
我们可以将连接信息存储在注册表中。将连接信息存储在注册表中可能会在部署时引起问题。以下命令可用于将连接信息存储在注册表中:
aspnet_setreg -k "software\applicationData" -u:UserID -p:Password
它会加密用户 ID 和密码,并将它们存储在指定的键中。
我们也可以将加密的连接字符串保存在 web.config 文件中。要加密 web.config 中的连接字符串,可以使用 aspnet_regiis 实用工具。(注意:有一些提供程序可以加密/解密连接字符串。您可以创建自己的加密/解密提供程序。)
4. DataReader 和 DataSet
您应该决定何时使用 DataReader
,何时使用 DataSet
。
避免使用 DataAdapter
的 Fill
方法,该方法接受 startRecord
和 maxRecord
作为参数。这只会用介于 startRecord
和 maxRecord
之间的记录来填充 DataSet
,尽管每次调用该方法时,它都会从数据库中获取所有数据。
在访问任何输出参数之前,应关闭 DataReader
。读取数据后,您应该关闭 DataReader
。如果您将 CommandBehaviour.CloseConnection
传递给 ExecuteReader
方法,则在关闭 DataReader
时,它将关闭关联的连接。
DataReader
不应通过多层进行访问。它设计用于连接式数据访问。
访问数据库列值时,应使用 GetString/GetInt32
等方法。这可以减少类型转换的开销并提高性能。单个关联连接上只能打开一个 DataReader
。
DataReader
的默认行为是每次读取时将整行加载到内存中。因此,我们可以随机访问当前行中的列。如果您不需要随机访问,可以将 CommandBehaviour.SequentialAccess
传递给 ExecuteReader
方法。这将更改 DataReader
的默认行为,并且仅在请求时才将数据加载到内存中。使用此行为,您需要按顺序访问列,并且一旦读取了某一列,就无法再读取其值。使用 SequentialAccess
行为可以获得更好的性能。
5. Command 对象
为了获得参数化命令更好的性能,您应该使用 Command.Prepare
。调用 Prepare
方法后,数据源会优化命令以供多次调用。
注意:对于 SQL Server 2000,命令已隐式优化,因此调用 Prepare
方法不会做任何额外的事情。然而,相同的 Prepare
命令对于 SQL Server 7.0 等数据源是有效的。
调用存储过程时,最好将 CommandType
设置为 StoredProcedure
。这将消除解析命令的需要。
如果您在读取所有记录之前关闭 DataReader
,则在调用 DataReader
的 Close
之前,您应该调用命令的 Cancel
。调用 Close
会导致 DataReader
检索挂起的结果并在关闭游标之前清空流。调用命令的 Cancel
会丢弃服务器上的结果,因此 DataReader
在关闭时无需读取。
注意:如果您要从命令返回输出参数,调用 Cancel
也会丢弃这些参数。因此,如果您需要任何输出参数,请不要调用命令的 Cancel
;而是调用 DataReader
的 Close
。
6. CommandBuilder
CommandBuilder
会根据 Select 命令为 Data Adapter 生成 insert/update/delete 命令。自动创建 insert/update/delete 命令会影响性能。如果您知道 insert/update/delete 的内容,则应显式创建它们。最好为 insert/update/delete 创建显式的存储过程并分配给它们。
CommandBuilder
使用 Data Adapter 的 SelectComand
属性来确定其他命令的值。如果 SelectCommand
发生更改,请记住调用 RefreshScheme
来更新命令属性。
只有当 Data Adapter 的命令属性为 null 时,CommandBuilder
才会为该命令属性生成命令。默认情况下,Data Adapter 的命令属性为 null。如果您显式设置了一个命令属性,CommandBuilder
不会覆盖它。您需要将命令属性设置为 null,才能让 CommandBuilder
为该命令属性生成命令。