9-1. Connect to a Database
Tải bản đầy đủ - 0trang
CHAPTER 9 ■ DATABASE ACCESS
•
The name of the target database server
•
The name of the database to open initially
•
Connection timeout values
•
Connection-pooling behavior (see recipe 9-2)
•
Authentication mechanisms to use when connecting to secured databases,
including provision of a username and password if needed
Once configured, call the connection object’s Open method to open the connection to the database.
You can then use the connection object to execute commands against the data source (discussed in
recipe 9-3). The properties of a connection object also allow you to retrieve information about the state
of a connection and the settings used to open the connection. When you’re finished with a connection,
you should always call its Close method to free the underlying database connection and system
resources. IDbConnection extends System.IDisposable, meaning that each connection class implements
the Dispose method. Dispose automatically calls Close, making the using statement a very clean and
efficient way of using connection objects in your code.
The Code
The following example demonstrates how to use both the SqlConnection and OleDbConnection classes to
open a connection to a Microsoft SQL Server Express database running on the local machine that uses
integrated Windows security:
using
using
using
using
System;
System.Data;
System.Data.SqlClient;
System.Data.OleDb;
namespace Apress.VisualCSharpRecipes.Chapter09
{
class Recipe09_01
{
public static void SqlConnectionExample()
{
// Create an empty SqlConnection object.
using (SqlConnection con = new SqlConnection())
{
// Configure the SqlConnection object's connection string.
con.ConnectionString =
@"Data Source=.\sqlexpress;" + // local SQL Server instance
"Database=Northwind;" +
// the sample Northwind DB
"Integrated Security=SSPI";
// integrated Windows security
// Open the database connection.
con.Open();
426
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
// Display information about the connection.
if (con.State == ConnectionState.Open)
{
Console.WriteLine("SqlConnection Information:");
Console.WriteLine(" Connection State = " + con.State);
Console.WriteLine(" Connection String = " +
con.ConnectionString);
Console.WriteLine(" Database Source = " + con.DataSource);
Console.WriteLine(" Database = " + con.Database);
Console.WriteLine(" Server Version = " + con.ServerVersion);
Console.WriteLine(" Workstation Id = " + con.WorkstationId);
Console.WriteLine(" Timeout = " + con.ConnectionTimeout);
Console.WriteLine(" Packet Size = " + con.PacketSize);
}
else
{
Console.WriteLine("SqlConnection failed to open.");
Console.WriteLine(" Connection State = " + con.State);
}
// At the end of the using block Dispose() calls Close().
}
}
public static void OleDbConnectionExample()
{
// Create an empty OleDbConnection object.
using (OleDbConnection con = new OleDbConnection())
{
// Configure the OleDbConnection object's connection string.
con.ConnectionString =
"Provider=SQLOLEDB;" +
// OLE DB Provider for SQL Server
@"Data Source=.\sqlexpress;" + // local SQL Server instance
"Initial Catalog=Northwind;" + // the sample Northwind DB
"Integrated Security=SSPI";
// integrated Windows security
// Open the database connection.
con.Open();
// Display information about the connection.
if (con.State == ConnectionState.Open)
{
Console.WriteLine("OleDbConnection Information:");
Console.WriteLine(" Connection State = " + con.State);
Console.WriteLine(" Connection String = " +
con.ConnectionString);
Console.WriteLine(" Database Source = " + con.DataSource);
Console.WriteLine(" Database = " + con.Database);
Console.WriteLine(" Server Version = " + con.ServerVersion);
Console.WriteLine(" Timeout = " + con.ConnectionTimeout);
}
427
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
else
{
Console.WriteLine("OleDbConnection failed to open.");
Console.WriteLine(" Connection State = " + con.State);
}
// At the end of the using block Dispose() calls Close().
}
}
public static void Main()
{
// Open connection using SqlConnection.
SqlConnectionExample();
Console.WriteLine(Environment.NewLine);
// Open connection using OleDbConnection.
OleDbConnectionExample();
// Wait to continue.
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Main method complete. Press Enter.");
Console.ReadLine();
}
}
}
9-2. Use Connection Pooling
Problem
You need to use a pool of database connections to improve application performance and scalability.
Solution
Configure the connection pool using settings in the connection string of a connection object.
How It Works
Connection pooling reduces the overhead associated with creating and destroying database
connections. Connection pooling also improves the scalability of solutions by reducing the number of
concurrent connections a database must maintain. Many of these connections sit idle for a significant
portion of their lifetimes. With connection pooling, instead of creating and opening a new connection
object whenever you need one, you take an already open connection from the connection pool. When
you have finished using the connection, instead of closing it, you return it to the pool and allow other
code to use it.
428
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
The SQL Server and Oracle data providers encapsulate connection-pooling functionality, which is
enabled by default. One connection pool is created for each unique connection string you specify when
you open a new connection. Each time you open a new connection with a connection string that you
used previously, the connection is taken from the existing pool. Only if you specify a different
connection string will the data provider create a new connection pool. You can control some
characteristics of your pool using the connection string settings described in Table 9-2.
■ Note Once created, a pool exists until your process terminates.
Table 9-2. Connection String Settings That Control Connection Pooling
Setting
Description
Connection
Lifetime
Specifies the maximum time in seconds that a connection is allowed to live in the pool
before it’s closed. The age of a connection is tested only when the connection is returned
to the pool. This setting is useful for minimizing pool size if the pool is not heavily used,
and also ensures optimal load balancing is achieved in clustered database environments.
The default value is 0, which means connections exist for the life of the current process.
Connection
Reset
Supported only by the SQL Server data provider. Specifies whether connections are reset
as they are taken from the pool. A value of True (the default) ensures that a connection’s
state is reset, but requires additional communication with the database.
Max Pool
Size
Specifies the maximum number of connections that should be in the pool. Connections
are created and added to the pool as required until this value is reached. If a request for a
connection is made but there are no free connections, the caller will block until a
connection becomes available. The default value is 100.
Min Pool
Size
Specifies the minimum number of connections that should be in the pool. On pool
creation, this number of connections is created and added to the pool. During periodic
maintenance, or when a connection is requested, connections are added to the pool to
ensure that the minimum number of connections are available. The default value is 0.
Pooling
Set to False to obtain a nonpooled connection. The default value is True.
The Code
The following example demonstrates the configuration of a connection pool that contains a minimum of
5 and a maximum of 15 connections. Connections expire after 10 minutes (600 seconds) and are reset
each time a connection is obtained from the pool. The example also demonstrates how to use the
Pooling setting to obtain a connection object that is not from a pool. This is useful if your application
uses a single long-lived connection to a database.
429
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
using System;
using System.Data.SqlClient;
namespace Apress.VisualCSharpRecipes.Chapter09
{
class Recipe09_02
{
public static void Main()
{
// Obtain a pooled connection.
using (SqlConnection con = new SqlConnection())
{
// Configure the SqlConnection object's connection string.
con.ConnectionString =
@"Data Source = .\sqlexpress;" +// local SQL Server instance
"Database = Northwind;" +
// the sample Northwind DB
"Integrated Security = SSPI;" + // integrated Windows security
"Min Pool Size = 5;" +
// configure minimum pool size
"Max Pool Size = 15;" +
// configure maximum pool size
"Connection Reset = True;" +
// reset connections each use
"Connection Lifetime = 600";
// set max connection lifetime
// Open the database connection.
con.Open();
// Access the database . . .
// At the end of the using block, the Dispose calls Close, which
// returns the connection to the pool for reuse.
}
// Obtain a nonpooled connection.
using (SqlConnection con = new SqlConnection())
{
// Configure the SqlConnection object's connection string.
con.ConnectionString =
@"Data Source = .\sqlexpress;" +//local SQL Server instance
"Database = Northwind;" +
//the sample Northwind DB
"Integrated Security = SSPI;" + //integrated Windows security
"Pooling = False";
//specify nonpooled connection
// Open the database connection.
con.Open();
// Access the database . . .
// At the end of the using block, the Dispose calls Close, which
// closes the nonpooled connection.
}
430
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
// Wait to continue.
Console.WriteLine(Environment.NewLine);
Console.WriteLine("Main method complete. Press Enter.");
Console.ReadLine();
}
}
}
Notes
The ODBC and OLE DB data providers also support connection pooling, but they do not implement
connection pooling within managed .NET classes, and you do not configure the pool in the same way as
you do for the SQL Server or Oracle data providers. ODBC connection pooling is managed by the ODBC
Driver Manager and configured using the ODBC Data Source Administrator tool in the Control Panel.
OLE DB connection pooling is managed by the native OLE DB implementation. The most you can do is
disable pooling by including the setting OLE DB Services=-4; in your connection string.
The SQL Server CE data provider does not support connection pooling, because SQL Server CE
supports only a single concurrent connection.
9-3. Create a Database Connection String Programmatically
Problem
You need to programmatically create or modify a syntactically correct connection string by working with
its component parts or parsing a given connection string.
Solution
Use the System.Data.Common.DbConnectionStringBuilder class or one of its strongly typed subclasses
that form part of an ADO.NET data provider.
How It Works
Connection strings are String objects that contain a set of configuration parameters in the form of
name/value pairs separated by semicolons. These configuration parameters instruct the ADO.NET
infrastructure how to open a connection to the data source you want to access and how to handle the life
cycle of connections to that data source. As a developer, you will often simply define your connection
string by hand and store it in a configuration file (see recipe 9-4). However, you may want to build a
connection string from component elements entered by a user, or you may want to parse an existing
connection string into its component parts so that you can manipulate it programmatically. The
DbConnectionStringBuilder class and the classes derived from it provide both these capabilities.
DbConnectionStringBuilder is a class used to create connection strings from name/value pairs or to
parse connection strings, but it does not enforce any logic on which configuration parameters are valid.
Instead, each data provider (except the SQL Server CE data provider) includes a unique implementation
derived from DbConnectionStringBuilder that accurately enforces the configuration rules for a
431
www.it-ebooks.info
CHAPTER 9 ■ DATABASE ACCESS
connection string of that type. Here is the list of available DbConnectionStringBuilder implementations
for standard data providers:
•
System.Data.Odbc.OdbcConnectionStringBuilder
•
System.Data.OleDb.OleDbConnectionStringBuilder
•
System.Data.OracleClient.OracleConnectionStringBuilder
•
System.Data.SqlClient.SqlConnectionStringBuilder
Each of these classes exposes properties for getting and setting the possible parameters for a
connection string of that type. To parse an existing connection string, pass it as an argument when
creating the DbConnectionStringBuilder-derived class, or set the ConnectionString property. If this
string contains a keyword not supported by the type of connection, an ArgumentException will be
thrown.
The Code
The following example demonstrates the use of the SqlConnectionStringBuilder class to parse and
construct SQL Server connection strings:
using System;
using System.Data.SqlClient;
namespace Apress.VisualCSharpRecipes.Chapter09
{
class Recipe09_03
{
public static void Main(string[] args)
{
string conString = @"Data Source=.\sqlexpress;" +
"Database=Northwind;Integrated Security=SSPI;" +
"Min Pool Size=5;Max Pool Size=15;Connection Reset=True;" +
"Connection Lifetime=600;";
// Parse the SQL Server connection string and display the component
// configuration parameters.
SqlConnectionStringBuilder sb1 =
new SqlConnectionStringBuilder(conString);
Console.WriteLine("Parsed SQL Connection String Parameters:");
Console.WriteLine(" Database Source = " + sb1.DataSource);
Console.WriteLine(" Database = " + sb1.InitialCatalog);
Console.WriteLine(" Use Integrated Security = "
+ sb1.IntegratedSecurity);
Console.WriteLine(" Min Pool Size = " + sb1.MinPoolSize);
Console.WriteLine(" Max Pool Size = " + sb1.MaxPoolSize);
Console.WriteLine(" Lifetime = " + sb1.LoadBalanceTimeout);
432
www.it-ebooks.info