Optimization techniques vary with the functionality in your application, so
here are some general tips to optimizing performance.
Precompile with the Native Image Generator
One of the tools with the .NET Framework SDK is the Native Image Generator
(ngen.exe). This tool precompiles your application and can improve that startup
times over JIT compiling. The .NET Documentation describes this tool as:
"The Native Image Generator creates a native image from a managed assembly and
installs it into the native image cache on the local computer. Running Ngen.exe
on an assembly allows the assembly to load and execute faster, because it
restores code and data structures from the native image cache rather than
generating them dynamically."
For example, the following line, typed at the command prompt, generates a native
image for myApplication.exe
ngen c:\myApplication.exe
Dispose of Resources
When you have a component that uses resources that need to be released,
consider implementing the IDisposable interface. This is the recommended way to
release resources, rather than relying on the garbage collector and the
Finalize method. The IDisposable interface has one method, Dispose(), that you
can implement to handle any necessary cleanup. Clients should call this method
prior to de-referencing your class, or letting it go out of scope. You can also
call this method from your component's Finalize method to properly free
resources for the cases where the the client does not call Dispose(), and the
garbage collector cleans up your object.
Resources that need to be freed include database connections and files. Here is
a list of some of the classes that implement the IDisposable interface.
BinaryReader & BinaryWriter
TextReader & TextWriter
Component
SqlConnection & OleDbConnection
SqlCommand & OleDbCommand
OleDbDataReader & SqlDataReader
Use Database Connection Pooling
In order to use the database connection pooling features of ADO.NET, the connection string must be the same. If you use windows authentication,
for authenticating users in the database, then connection pooling will not be used. To change this, modify your application so that it uses
a single username and password to connect to the database for all users, and implement security at the application level.
Use the SqlClient Namespace
When accessing SQL Server databases, the SqlClient namespace offers
significantly better performance than the OleDb namespace, since the classes in
the SqlClient namespace communicate using SQL Server's native tabular data
format. When the database is SQL Server and performance is paramount, use the
System.Data.SqlClient namespace.
Use SqlReader for Forward-Only Data
If you need data from a database and only need to loop through it, perhaps to
populate a select box, use a DataReader over a DataSet. The DataReader, such as
the SqlDataReader, does not store the data in memory like the dataset, and
offers much better performance in forward-only scenarios.
Cache Stored Procedure Parameters
When using stored procedures multiple times, reuse or cache the Parameters to
reduce the overhead of preparing new parameter objects for every call. Although
not covered on the exam, you should take a look at
Microsoft's Data Access Application Block for .NET, that was built
using some best practices of data access encapsulation, and features a
parameter cache to improve performance.
Prepare Commands
The Prepare method, of the SqlCommand and OleDbCommand objects, creates a
compiled version of the command. This can improve performance if the command is
going to be re-used one or more times. For instance, the following code sample
from the .NET Documentation, shows a command being prepared, and later used
again. When the command is re-used, the compiled version is executed.
//Set Command object Properties
command.CommandText
="insert into Region (RegionID, RegionDescription) values (@id, @desc)"; command.Parameters.Add
("@id",id); command.Parameters.Add
("@desc",desc);
//Prepare a compiled version
command.Prepare();
//Execute
command.ExecuteNonQuery();
// Change param values and call execute. This time the prepared command will be executed.
command.Parameters[0].Value
=21; command.Parameters[1].Value
="mySecondRegion"; command.ExecuteNonQuery();
Consider Asynchronous calls and Remoting
If you have a component that takes a while to complete, consider calling it
asynchronously so the calling application can continue working, or using
Remoting to offload the load of that component to a dedicated server.
Compile in Release Mode
During development, you'll compile in Debug mode to get additional information
about errors, and to enable debugging. However, for your production
environment, be sure to compile and publish your code in the Release
configuration. This removes the overhead of the debug code.