SFI - ROPC: Clean up adonet files (#42289)
This commit is contained in:
Родитель
7f1596466d
Коммит
108c1d7afe
|
@ -1,42 +1,34 @@
|
|||
---
|
||||
title: "Asynchronous Programming"
|
||||
description: Learn about asynchronous programming in the .NET Framework Data Provider for SQL Server, including enhancements introduced in .NET Framework 4.5.
|
||||
description: Learn about asynchronous programming in .NET Framework Data Provider for SQL Server, including enhancements introduced in .NET Framework 4.5.
|
||||
ms.date: "10/18/2018"
|
||||
ms.assetid: 85da7447-7125-426e-aa5f-438a290d1f77
|
||||
---
|
||||
|
||||
# Asynchronous Programming
|
||||
# Asynchronous programming
|
||||
|
||||
This topic discusses support for asynchronous programming in the .NET Framework Data Provider for SQL Server (SqlClient) including enhancements made to support asynchronous programming functionality that was introduced in .NET Framework 4.5.
|
||||
This article discusses support for asynchronous programming in .NET Framework Data Provider for SQL Server (SqlClient), including enhancements made to support asynchronous programming functionality that was introduced in .NET Framework 4.5.
|
||||
|
||||
## Legacy Asynchronous Programming
|
||||
## Legacy asynchronous programming
|
||||
|
||||
Prior to .NET Framework 4.5, asynchronous programming with SqlClient was done with the following methods and the `Asynchronous Processing=true` connection property:
|
||||
|
||||
1. <xref:System.Data.SqlClient.SqlCommand.BeginExecuteNonQuery%2A?displayProperty=nameWithType>
|
||||
- <xref:System.Data.SqlClient.SqlCommand.BeginExecuteNonQuery%2A?displayProperty=nameWithType>
|
||||
- <xref:System.Data.SqlClient.SqlCommand.BeginExecuteReader%2A?displayProperty=nameWithType>
|
||||
- <xref:System.Data.SqlClient.SqlCommand.BeginExecuteXmlReader%2A?displayProperty=nameWithType>
|
||||
|
||||
2. <xref:System.Data.SqlClient.SqlCommand.BeginExecuteReader%2A?displayProperty=nameWithType>
|
||||
|
||||
3. <xref:System.Data.SqlClient.SqlCommand.BeginExecuteXmlReader%2A?displayProperty=nameWithType>
|
||||
|
||||
This functionality remains in SqlClient in .NET Framework 4.5.
|
||||
This functionality remained in SqlClient in .NET Framework 4.5.
|
||||
|
||||
> [!TIP]
|
||||
> Beginning in .NET Framework 4.5, these legacy methods no longer require `Asynchronous Processing=true` in the connection string.
|
||||
|
||||
## Asynchronous Programming Features Added in .NET Framework 4.5
|
||||
## Asynchronous programming features added in .NET Framework 4.5
|
||||
|
||||
The new asynchronous programming feature provides a simple technique to make code asynchronous.
|
||||
|
||||
For more information about the asynchronous programming feature that was introduced in .NET Framework 4.5, see:
|
||||
The asynchronous programming feature provides a simple technique to make code asynchronous. For more information about the asynchronous programming feature that was introduced in .NET Framework 4.5, see:
|
||||
|
||||
- [Asynchronous programming in C#](../../../csharp/asynchronous-programming/index.md)
|
||||
|
||||
- [Asynchronous Programming with Async and Await (Visual Basic)](../../../visual-basic/programming-guide/concepts/async/index.md)
|
||||
|
||||
- [Using SqlDataReader’s new async methods in .NET Framework 4.5 (Part 1)](/archive/blogs/adonet/using-sqldatareaders-new-async-methods-in-net-4-5)
|
||||
|
||||
- [Using SqlDataReader’s new async methods in .NET Framework 4.5 (Part 2)](/archive/blogs/adonet/using-sqldatareaders-new-async-methods-in-net-4-5-part-2-examples)
|
||||
- [Using SqlDataReader's new async methods in .NET Framework 4.5 (Part 1)](/archive/blogs/adonet/using-sqldatareaders-new-async-methods-in-net-4-5)
|
||||
- [Using SqlDataReader's new async methods in .NET Framework 4.5 (Part 2)](/archive/blogs/adonet/using-sqldatareaders-new-async-methods-in-net-4-5-part-2-examples)
|
||||
|
||||
When your user interface is unresponsive or your server does not scale, it is likely that you need your code to be more asynchronous. Writing asynchronous code has traditionally involved installing a callback (also called continuation) to express the logic that occurs after the asynchronous operation finishes. This complicates the structure of asynchronous code as compared with synchronous code.
|
||||
|
||||
|
@ -47,55 +39,39 @@ The `async` modifier specifies that a method is asynchronous. When calling an `a
|
|||
> [!WARNING]
|
||||
> Asynchronous calls are not supported if an application also uses the `Context Connection` connection string keyword.
|
||||
|
||||
Calling an `async` method does not allocate any additional threads. It may use the existing I/O completion thread briefly at the end.
|
||||
Calling an `async` method does not allocate any additional threads. It might use the existing I/O completion thread briefly at the end.
|
||||
|
||||
The following methods were added in .NET Framework 4.5 to support asynchronous programming:
|
||||
|
||||
- <xref:System.Data.Common.DbConnection.OpenAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbCommand.ExecuteDbDataReaderAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbCommand.ExecuteNonQueryAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbCommand.ExecuteReaderAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbCommand.ExecuteScalarAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbDataReader.GetFieldValueAsync%2A>
|
||||
|
||||
- <xref:System.Data.Common.DbDataReader.IsDBNullAsync%2A>
|
||||
|
||||
- <xref:System.Data.Common.DbDataReader.NextResultAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.Common.DbDataReader.ReadAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlConnection.OpenAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlCommand.ExecuteNonQueryAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlCommand.ExecuteReaderAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlCommand.ExecuteScalarAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlCommand.ExecuteXmlReaderAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.NextResultAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.ReadAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlBulkCopy.WriteToServerAsync%2A?displayProperty=nameWithType>
|
||||
|
||||
Other asynchronous members were added to support [SqlClient Streaming Support](sqlclient-streaming-support.md).
|
||||
|
||||
> [!TIP]
|
||||
> The new asynchronous methods don't require `Asynchronous Processing=true` in the connection string.
|
||||
> The newer asynchronous methods don't require `Asynchronous Processing=true` in the connection string.
|
||||
|
||||
### Synchronous to Asynchronous Connection Open
|
||||
### Synchronous to asynchronous connection open
|
||||
|
||||
You can upgrade an existing application to use the new asynchronous feature. For example, assume an application has a synchronous connection algorithm and blocks the UI thread every time it connects to the database and, once connected, the application calls a stored procedure that signals other users of the one who just signed in.
|
||||
You can upgrade an older application to use the newer asynchronous feature. For example, assume an application has a synchronous connection algorithm and blocks the UI thread every time it connects to the database and, once connected, the application calls a stored procedure that signals other users of the one who just signed in.
|
||||
|
||||
```csharp
|
||||
using SqlConnection conn = new SqlConnection("…");
|
||||
using SqlConnection conn = new SqlConnection("...");
|
||||
{
|
||||
conn.Open();
|
||||
using (SqlCommand cmd = new SqlCommand("StoredProcedure_Logon", conn))
|
||||
|
@ -105,7 +81,7 @@ using SqlConnection conn = new SqlConnection("…");
|
|||
}
|
||||
```
|
||||
|
||||
When converted to use the new asynchronous functionality, the program would look like:
|
||||
When converted to use the newer asynchronous functionality, the program would look like:
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
|
@ -121,7 +97,7 @@ class A {
|
|||
}
|
||||
|
||||
public static void Main() {
|
||||
using (SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI")) {
|
||||
using (SqlConnection conn = new SqlConnection("...")) {
|
||||
SqlCommand command = new SqlCommand("select top 2 * from orders", conn);
|
||||
|
||||
int result = A.Method(conn, command).Result;
|
||||
|
@ -134,13 +110,13 @@ class A {
|
|||
}
|
||||
```
|
||||
|
||||
### Adding the New Asynchronous Feature in an Existing Application (Mixing Old and New Patterns)
|
||||
### Add the new asynchronous feature in an existing app (mix old and new patterns)
|
||||
|
||||
It is also possible to add new asynchronous capability (SqlConnection::OpenAsync) without changing the existing asynchronous logic. For example, if an application currently uses:
|
||||
It is also possible to add new asynchronous capability (`SqlConnection::OpenAsync`) without changing the existing asynchronous logic. For example, if an application currently uses:
|
||||
|
||||
```csharp
|
||||
AsyncCallback productList = new AsyncCallback(ProductList);
|
||||
SqlConnection conn = new SqlConnection("…");
|
||||
SqlConnection conn = new SqlConnection("...");
|
||||
conn.Open();
|
||||
SqlCommand cmd = new SqlCommand("SELECT * FROM [Current Product List]", conn);
|
||||
IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
|
||||
|
@ -156,15 +132,10 @@ using System.Threading.Tasks;
|
|||
class A {
|
||||
static void ProductList(IAsyncResult result) { }
|
||||
|
||||
public static void Main() {
|
||||
// AsyncCallback productList = new AsyncCallback(ProductList);
|
||||
// SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI");
|
||||
// conn.Open();
|
||||
// SqlCommand cmd = new SqlCommand("select top 2 * from orders", conn);
|
||||
// IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
AsyncCallback productList = new AsyncCallback(ProductList);
|
||||
SqlConnection conn = new SqlConnection("Data Source=(local); Initial Catalog=NorthWind; Integrated Security=SSPI");
|
||||
SqlConnection conn = new SqlConnection("...");
|
||||
conn.OpenAsync().ContinueWith((task) => {
|
||||
SqlCommand cmd = new SqlCommand("select top 2 * from orders", conn);
|
||||
IAsyncResult ia = cmd.BeginExecuteReader(productList, cmd);
|
||||
|
@ -173,9 +144,9 @@ class A {
|
|||
}
|
||||
```
|
||||
|
||||
### Using the Base Provider Model and the New Asynchronous Feature
|
||||
### Use the base provider model and the new asynchronous feature
|
||||
|
||||
You may need to create a tool that is able to connect to different databases and execute queries. You can use the base provider model and the new asynchronous feature.
|
||||
You might need to create a tool that is able to connect to different databases and execute queries. You can use the base provider model and the new asynchronous feature.
|
||||
|
||||
The Microsoft Distributed Transaction Controller (MSDTC) must be enabled on the server to use distributed transactions. For information on how to enable MSDTC, see [How to Enable MSDTC on a Web Server](/previous-versions/commerce-server/dd327979(v=cs.90)).
|
||||
|
||||
|
@ -222,7 +193,9 @@ class A {
|
|||
}
|
||||
```
|
||||
|
||||
### Using SQL Transactions and the New Asynchronous Feature
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Use SQL transactions and the new asynchronous feature
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
|
@ -231,8 +204,7 @@ using System.Threading.Tasks;
|
|||
|
||||
class Program {
|
||||
static void Main() {
|
||||
string connectionString =
|
||||
"Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local)";
|
||||
string connectionString = "...";
|
||||
Task task = ExecuteSqlTransaction(connectionString);
|
||||
task.Wait();
|
||||
}
|
||||
|
@ -288,9 +260,9 @@ class Program {
|
|||
}
|
||||
```
|
||||
|
||||
### Using SQL Transactions and the New Asynchronous Feature
|
||||
### Use SQL transactions and the new asynchronous feature
|
||||
|
||||
In an enterprise application, you may need to add distributed transactions in some scenarios, to enable transactions between multiple database servers. You can use the System.Transactions namespace and enlist a distributed transaction, as follows:
|
||||
In an enterprise application, you might need to add distributed transactions in some scenarios, to enable transactions between multiple database servers. You can use the <xref:System.Transactions> namespace and enlist a distributed transaction, as follows:
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
|
@ -350,7 +322,9 @@ class Program {
|
|||
}
|
||||
```
|
||||
|
||||
### Cancelling an Asynchronous Operation
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Cancel an asynchronous operation
|
||||
|
||||
You can cancel an asynchronous request by using the <xref:System.Threading.CancellationToken>.
|
||||
|
||||
|
@ -380,7 +354,7 @@ namespace Samples {
|
|||
}
|
||||
|
||||
static async Task CancellingAsynchronousOperations(CancellationToken cancellationToken) {
|
||||
using (SqlConnection connection = new SqlConnection("Server=(local);Integrated Security=true")) {
|
||||
using (SqlConnection connection = new SqlConnection("...")) {
|
||||
await connection.OpenAsync(cancellationToken);
|
||||
|
||||
SqlCommand command = new SqlCommand("WAITFOR DELAY '00:10:00'", connection);
|
||||
|
@ -391,7 +365,7 @@ namespace Samples {
|
|||
}
|
||||
```
|
||||
|
||||
### Asynchronous Operations with SqlBulkCopy
|
||||
### Asynchronous operations with SqlBulkCopy
|
||||
|
||||
Asynchronous capabilities were also added to <xref:System.Data.SqlClient.SqlBulkCopy?displayProperty=nameWithType> with <xref:System.Data.SqlClient.SqlBulkCopy.WriteToServerAsync%2A?displayProperty=nameWithType>.
|
||||
|
||||
|
@ -422,18 +396,7 @@ namespace SqlBulkCopyAsyncCodeSample {
|
|||
[notes] [varchar](200) NULL,
|
||||
[pubdate] [datetime] NOT NULL)";
|
||||
|
||||
// Replace the connection string if needed, for instance to connect to SQL Express: @"Server=(local)\SQLEXPRESS;Database=Demo;Integrated Security=true"
|
||||
// static string connectionString = @"Server=(localdb)\V11.0;Database=Demo";
|
||||
static string connectionString = @"Server=(local);Database=Demo;Integrated Security=true";
|
||||
|
||||
// static string odbcConnectionString = @"Driver={SQL Server};Server=(localdb)\V11.0;UID=oledb;Pwd=[PLACEHOLDER];Database=Demo";
|
||||
static string odbcConnectionString = @"Driver={SQL Server};Server=(local);Database=Demo;Integrated Security=true";
|
||||
|
||||
// static string marsConnectionString = @"Server=(localdb)\V11.0;Database=Demo;MultipleActiveResultSets=true;";
|
||||
static string marsConnectionString = @"Server=(local);Database=Demo;MultipleActiveResultSets=true;Integrated Security=true";
|
||||
|
||||
// Replace the Server name with your actual sql azure server name and User ID/Password
|
||||
static string azureConnectionString = @"Server=SqlAzure;User ID=myUserID;Password=myPassword;Database=Demo";
|
||||
static string connectionString = "...";
|
||||
|
||||
static void Main(string[] args) {
|
||||
SynchronousSqlBulkCopy();
|
||||
|
@ -441,8 +404,6 @@ namespace SqlBulkCopyAsyncCodeSample {
|
|||
MixSyncAsyncSqlBulkCopy().Wait();
|
||||
AsyncSqlBulkCopyNotifyAfter().Wait();
|
||||
AsyncSqlBulkCopyDataRows().Wait();
|
||||
// AsyncSqlBulkCopySqlServerToSqlAzure().Wait();
|
||||
// AsyncSqlBulkCopyCancel().Wait();
|
||||
AsyncSqlBulkCopyMARS().Wait();
|
||||
}
|
||||
|
||||
|
@ -491,7 +452,7 @@ namespace SqlBulkCopyAsyncCodeSample {
|
|||
|
||||
// 3.2 Add new Async.NET capabilities in an existing application (Mixing synchronous and asynchronous calls)
|
||||
private static async Task MixSyncAsyncSqlBulkCopy() {
|
||||
using (OdbcConnection odbcconn = new OdbcConnection(odbcConnectionString)) {
|
||||
using (OdbcConnection odbcconn = new OdbcConnection(connectionString)) {
|
||||
odbcconn.Open();
|
||||
using (OdbcCommand odbccmd = new OdbcCommand(selectStatement, odbcconn)) {
|
||||
using (OdbcDataReader odbcreader = odbccmd.ExecuteReader()) {
|
||||
|
@ -559,54 +520,9 @@ namespace SqlBulkCopyAsyncCodeSample {
|
|||
}
|
||||
}
|
||||
|
||||
// 3.5 Copying data from SQL Server to SQL Azure in .NET Framework 4.5
|
||||
//private static async Task AsyncSqlBulkCopySqlServerToSqlAzure() {
|
||||
// using (SqlConnection srcConn = new SqlConnection(connectionString))
|
||||
// using (SqlConnection destConn = new SqlConnection(azureConnectionString)) {
|
||||
// await srcConn.OpenAsync();
|
||||
// await destConn.OpenAsync();
|
||||
// using (SqlCommand srcCmd = new SqlCommand(selectStatement, srcConn)) {
|
||||
// using (SqlDataReader reader = await srcCmd.ExecuteReaderAsync()) {
|
||||
// string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
|
||||
// using (SqlCommand destCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), destConn)) {
|
||||
// await destCmd.ExecuteNonQueryAsync();
|
||||
// using (SqlBulkCopy bcp = new SqlBulkCopy(destConn)) {
|
||||
// bcp.DestinationTableName = temptable;
|
||||
// await bcp.WriteToServerAsync(reader);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// 3.6 Cancelling an Asynchronous Operation to SQL Azure
|
||||
//private static async Task AsyncSqlBulkCopyCancel() {
|
||||
// CancellationTokenSource cts = new CancellationTokenSource();
|
||||
// using (SqlConnection srcConn = new SqlConnection(connectionString))
|
||||
// using (SqlConnection destConn = new SqlConnection(azureConnectionString)) {
|
||||
// await srcConn.OpenAsync(cts.Token);
|
||||
// await destConn.OpenAsync(cts.Token);
|
||||
// using (SqlCommand srcCmd = new SqlCommand(selectStatement, srcConn)) {
|
||||
// using (SqlDataReader reader = await srcCmd.ExecuteReaderAsync(cts.Token)) {
|
||||
// string temptable = "[#" + Guid.NewGuid().ToString("N") + "]";
|
||||
// using (SqlCommand destCmd = new SqlCommand(string.Format(createDestTableStatement, temptable), destConn)) {
|
||||
// await destCmd.ExecuteNonQueryAsync(cts.Token);
|
||||
// using (SqlBulkCopy bcp = new SqlBulkCopy(destConn)) {
|
||||
// bcp.DestinationTableName = temptable;
|
||||
// await bcp.WriteToServerAsync(reader, cts.Token);
|
||||
// //Cancel Async SqlBulCopy Operation after 200 ms
|
||||
// cts.CancelAfter(200);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// 3.7 Using Async.Net and MARS
|
||||
private static async Task AsyncSqlBulkCopyMARS() {
|
||||
using (SqlConnection marsConn = new SqlConnection(marsConnectionString)) {
|
||||
using (SqlConnection marsConn = new SqlConnection(connectionString)) {
|
||||
await marsConn.OpenAsync();
|
||||
|
||||
SqlCommand titlesCmd = new SqlCommand("SELECT * FROM [pubs].[dbo].[titles]", marsConn);
|
||||
|
@ -634,7 +550,7 @@ namespace SqlBulkCopyAsyncCodeSample {
|
|||
}
|
||||
```
|
||||
|
||||
## Asynchronously Using Multiple Commands with MARS
|
||||
## Asynchronously use multiple commands with MARS
|
||||
|
||||
The example opens a single connection to the **AdventureWorks** database. Using a <xref:System.Data.SqlClient.SqlCommand> object, a <xref:System.Data.SqlClient.SqlDataReader> is created. As the reader is used, a second <xref:System.Data.SqlClient.SqlDataReader> is opened, using data from the first <xref:System.Data.SqlClient.SqlDataReader> as input to the WHERE clause for the second reader.
|
||||
|
||||
|
@ -648,12 +564,14 @@ using System.Data.SqlClient;
|
|||
using System.Threading.Tasks;
|
||||
|
||||
class Class1 {
|
||||
static void Main() {
|
||||
static void Main()
|
||||
{
|
||||
Task task = MultipleCommands();
|
||||
task.Wait();
|
||||
}
|
||||
|
||||
static async Task MultipleCommands() {
|
||||
static async Task MultipleCommands()
|
||||
{
|
||||
// By default, MARS is disabled when connecting to a MARS-enabled.
|
||||
// It must be enabled in the connection string.
|
||||
string connectionString = GetConnectionString();
|
||||
|
@ -697,15 +615,10 @@ class Class1 {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString() {
|
||||
// To avoid storing the connection string in your code, you can retrieve it from a configuration file.
|
||||
return "Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks;MultipleActiveResultSets=True";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Asynchronously Reading and Updating Data with MARS
|
||||
## Asynchronously read and update data with MARS
|
||||
|
||||
MARS allows a connection to be used for both read operations and data manipulation language (DML) operations with more than one pending operation. This feature eliminates the need for an application to deal with connection-busy errors. In addition, MARS can replace the user of server-side cursors, which generally consume more resources. Finally, because multiple operations can operate on a single connection, they can share the same transaction context, eliminating the need to use **sp_getbindtoken** and **sp_bindsession** system stored procedures.
|
||||
|
||||
|
@ -814,11 +727,6 @@ class Program {
|
|||
Console.WriteLine("Transaction Rolled Back");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString() {
|
||||
// To avoid storing the connection string in your code, you can retrieve it from a configuration file.
|
||||
return "Data Source=(local);Integrated Security=SSPI;Initial Catalog=AdventureWorks;MultipleActiveResultSets=True";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -1,213 +1,222 @@
|
|||
---
|
||||
description: "Learn more about: Code Access Security and ADO.NET"
|
||||
description: "Learn more about: Code Access Security and ADO.NET. Whether the code is allowed to run or not depends on the code's origin or other aspects of its identity."
|
||||
title: "Code Access Security"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 93e099eb-daa1-4f1e-b031-c1e10a996f88
|
||||
---
|
||||
# Code Access Security and ADO.NET
|
||||
# Code access security and ADO.NET
|
||||
|
||||
.NET Framework offers role-based security as well as code access security (CAS), both of which are implemented using a common infrastructure supplied by the common language runtime (CLR). In the world of unmanaged code, most applications execute with the permissions of the user or principal. As a result, computer systems can be damaged and private data compromised when malicious or error-filled software is run by a user with elevated privileges.
|
||||
|
||||
By contrast, managed code executing in .NET Framework includes code access security, which applies to code alone. Whether the code is allowed to run or not depends on the code's origin or other aspects of the code's identity, not solely the identity of the principal. This reduces the likelihood that managed code can be misused.
|
||||
.NET Framework offers role-based security as well as code access security (CAS), both of which are implemented using a common infrastructure supplied by the common language runtime (CLR). In the world of unmanaged code, most applications execute with the permissions of the user or principal. As a result, computer systems can be damaged and private data compromised when malicious or error-filled software is run by a user with elevated privileges.
|
||||
|
||||
By contrast, managed code executing in .NET Framework includes code access security, which applies to code alone. Whether the code is allowed to run or not depends on the code's origin or other aspects of the code's identity, not solely the identity of the principal. This reduces the likelihood that managed code can be misused.
|
||||
|
||||
[!INCLUDE [cas-deprecated](../../../../includes/cas-deprecated.md)]
|
||||
|
||||
## Code Access Permissions
|
||||
|
||||
When code is executed, it presents evidence that is evaluated by the CLR security system. Typically, this evidence comprises the origin of the code including URL, site, and zone, and digital signatures that ensure the identity of the assembly.
|
||||
|
||||
The CLR allows code to perform only those operations that the code has permission to perform. Code can request permissions, and those requests are honored based on the security policy set by an administrator.
|
||||
|
||||
## Code access permissions
|
||||
|
||||
When code is executed, it presents evidence that is evaluated by the CLR security system. Typically, this evidence comprises the origin of the code including URL, site, and zone, and digital signatures that ensure the identity of the assembly.
|
||||
|
||||
The CLR allows code to perform only those operations that the code has permission to perform. Code can request permissions, and those requests are honored based on the security policy set by an administrator.
|
||||
|
||||
> [!NOTE]
|
||||
> Code executing in the CLR cannot grant permissions to itself. For example, code can request and be granted fewer permissions than a security policy allows, but it will never be granted more permissions. When granting permissions, start with no permissions at all and then add the narrowest permissions for the particular task being performed. Starting with all permissions and then denying individual ones leads to insecure applications that may contain unintentional security holes from granting more permissions than required. For more information, see [Configuring Security Policy](/previous-versions/dotnet/netframework-4.0/7c9c2y1w(v=vs.100)) and [Security Policy Management](/previous-versions/dotnet/netframework-4.0/c1k0eed6(v=vs.100)).
|
||||
|
||||
There are three types of code access permissions:
|
||||
|
||||
- `Code access permissions` derive from the <xref:System.Security.CodeAccessPermission> class. Permissions are required in order to access protected resources, such as files and environment variables, and to perform protected operations, such as accessing unmanaged code.
|
||||
|
||||
- `Identity permissions` represent characteristics that identify an assembly. Permissions are granted to an assembly based on evidence, which can include items such as a digital signature or where the code originated. Identity permissions also derive from the <xref:System.Security.CodeAccessPermission> base class.
|
||||
|
||||
- `Role-based security permissions` are based on whether a principal has a specified identity or is a member of a specified role. The <xref:System.Security.Permissions.PrincipalPermission> class allows both declarative and imperative permission checks against the active principal.
|
||||
|
||||
To determine whether code is authorized to access a resource or perform an operation, the runtime's security system traverses the call stack, comparing the granted permissions of each caller to the permission being demanded. If any caller in the call stack does not have the demanded permission, a <xref:System.Security.SecurityException> is thrown and access is refused.
|
||||
|
||||
### Requesting Permissions
|
||||
> Code executing in the CLR cannot grant permissions to itself. For example, code can request and be granted fewer permissions than a security policy allows, but it will never be granted more permissions. When granting permissions, start with no permissions at all and then add the narrowest permissions for the particular task being performed. Starting with all permissions and then denying individual ones leads to insecure applications that may contain unintentional security holes from granting more permissions than required. For more information, see [Configuring Security Policy](/previous-versions/dotnet/netframework-4.0/7c9c2y1w(v=vs.100)) and [Security Policy Management](/previous-versions/dotnet/netframework-4.0/c1k0eed6(v=vs.100)).
|
||||
|
||||
The purpose of requesting permissions is to inform the runtime which permissions your application requires in order to run, and to ensure that it receives only the permissions that it actually needs. For example, if your application needs to write data to the local disk, it requires <xref:System.Security.Permissions.FileIOPermission>. If that permission hasn't been granted, the application will fail when it attempts to write to the disk. However, if the application requests `FileIOPermission` and that permission has not been granted, the application will generate the exception at the outset and will not load.
|
||||
|
||||
In a scenario where the application only needs to read data from the disk, you can request that it never be granted any write permissions. In the event of a bug or a malicious attack, your code cannot damage the data on which it operates. For more information, see [Requesting Permissions](/previous-versions/dotnet/netframework-4.0/yd267cce(v=vs.100)).
|
||||
|
||||
## Role-Based Security and CAS
|
||||
There are three types of code access permissions:
|
||||
|
||||
Implementing both role-based security and code-accessed security (CAS) enhances overall security for your application. Role-based security can be based on a Windows account or a custom identity, making information about the security principal available to the current thread. In addition, applications are often required to provide access to data or resources based on credentials supplied by the user. Typically, such applications check the role of a user and provide access to resources based on those roles.
|
||||
|
||||
Role-based security enables a component to identify current users and their associated roles at run time. This information is then mapped using a CAS policy to determine the set of permissions granted at run time. For a specified application domain, the host can change the default role-based security policy and set a default security principal that represents a user and the roles associated with that user.
|
||||
|
||||
The CLR uses permissions to implement its mechanism for enforcing restrictions on managed code. Role-based security permissions provide a mechanism for discovering whether a user (or the agent acting on the user's behalf) has a particular identity or is a member of a specified role. For more information, see [Security Permissions](/previous-versions/dotnet/netframework-4.0/5ba4k1c5(v=vs.100)).
|
||||
|
||||
Depending on the type of application you are building, you should also consider implementing role-based permissions in the database. For more information on role-based security in SQL Server, see [SQL Server Security](/previous-versions/dotnet/framework/data/adonet/sql/sql-server-security).
|
||||
|
||||
## Assemblies
|
||||
- `Code access permissions` derive from the <xref:System.Security.CodeAccessPermission> class. Permissions are required in order to access protected resources, such as files and environment variables, and to perform protected operations, such as accessing unmanaged code.
|
||||
- `Identity permissions` represent characteristics that identify an assembly. Permissions are granted to an assembly based on evidence, which can include items such as a digital signature or where the code originated. Identity permissions also derive from the <xref:System.Security.CodeAccessPermission> base class.
|
||||
- `Role-based security permissions` are based on whether a principal has a specified identity or is a member of a specified role. The <xref:System.Security.Permissions.PrincipalPermission> class allows both declarative and imperative permission checks against the active principal.
|
||||
|
||||
Assemblies form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions for a .NET Framework application. An assembly provides a collection of types and resources that are built to work together and form a logical unit of functionality. To the CLR, a type does not exist outside the context of an assembly. For more information on creating and deploying assemblies, see [Programming with Assemblies](../../../standard/assembly/index.md).
|
||||
|
||||
### Strong-naming Assemblies
|
||||
To determine whether code is authorized to access a resource or perform an operation, the runtime's security system traverses the call stack, comparing the granted permissions of each caller to the permission being demanded. If any caller in the call stack does not have the demanded permission, a <xref:System.Security.SecurityException> is thrown and access is refused.
|
||||
|
||||
A strong name, or digital signature, consists of the assembly's identity, which includes its simple text name, version number, and culture information (if provided), plus a public key and a digital signature. The digital signature is generated from an assembly file using the corresponding private key. The assembly file contains the assembly manifest, which contains the names and hashes of all the files that make up the assembly.
|
||||
|
||||
Strong naming an assembly gives an application or component a unique identity that other software can use to refer explicitly to it. Strong naming guards assemblies against being spoofed by an assembly that contains hostile code. Strong-naming also ensures versioning consistency among different versions of a component. You must strong name assemblies that will be deployed to the Global Assembly Cache (GAC). For more information, see [Creating and Using Strong-Named Assemblies](../../../standard/assembly/create-use-strong-named.md).
|
||||
|
||||
## Partial Trust in ADO.NET 2.0
|
||||
### Request permissions
|
||||
|
||||
In ADO.NET 2.0, the .NET Framework Data Provider for SQL Server, the .NET Framework Data Provider for OLE DB, the .NET Framework Data Provider for ODBC, and the .NET Framework Data Provider for Oracle can now all run in partially trusted environments. In previous releases of the .NET Framework, only <xref:System.Data.SqlClient> was supported in less than full-trust applications.
|
||||
|
||||
At minimum, a partially trusted application using the SQL Server provider must have execution and <xref:System.Data.SqlClient.SqlClientPermission> permissions.
|
||||
|
||||
### Permission Attribute Properties for Partial Trust
|
||||
The purpose of requesting permissions is to inform the runtime which permissions your application requires in order to run, and to ensure that it receives only the permissions that it actually needs. For example, if your application needs to write data to the local disk, it requires <xref:System.Security.Permissions.FileIOPermission>. If that permission hasn't been granted, the application will fail when it attempts to write to the disk. However, if the application requests `FileIOPermission` and that permission has not been granted, the application will generate the exception at the outset and will not load.
|
||||
|
||||
For partial trust scenarios, you can use <xref:System.Data.SqlClient.SqlClientPermissionAttribute> members to further restrict the capabilities available for the .NET Framework Data Provider for SQL Server.
|
||||
|
||||
The following table lists the available <xref:System.Data.SqlClient.SqlClientPermissionAttribute> properties and their descriptions:
|
||||
|
||||
|Permission attribute property|Description|
|
||||
|-----------------------------------|-----------------|
|
||||
|`Action`|Gets or sets a security action. Inherited from <xref:System.Security.Permissions.SecurityAttribute>.|
|
||||
|`AllowBlankPassword`|Enables or disables the use of a blank password in a connection string. Valid values are `true` (to enable the use of blank passwords) and `false` (to disable the use of blank passwords). Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`ConnectionString`|Identifies a permitted connection string. Multiple connection strings can be identified. **Note:** Do not include a user ID or password in your connection string. In this release, you cannot change connection string restrictions using the .NET Framework Configuration Tool. <br /><br /> Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`KeyRestrictions`|Identifies connection string parameters that are allowed or disallowed. Connection string parameters are identified in the form *\<parameter name>=*. Multiple parameters can be specified, delimited using a semicolon (;). **Note:** If you do not specify `KeyRestrictions`, but you set `KeyRestrictionBehavior` property to `AllowOnly` or `PreventUsage`, no additional connection string parameters are allowed. Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`KeyRestrictionBehavior`|Identifies the connection string parameters as the only additional parameters allowed (`AllowOnly`), or identifies the additional parameters that are not allowed (`PreventUsage`). `AllowOnly` is the default. Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`TypeID`|Gets a unique identifier for this attribute when implemented in a derived class. Inherited from <xref:System.Attribute>.|
|
||||
|`Unrestricted`|Indicates whether unrestricted permission to the resource is declared. Inherited from <xref:System.Security.Permissions.SecurityAttribute>.|
|
||||
|
||||
#### ConnectionString Syntax
|
||||
In a scenario where the application only needs to read data from the disk, you can request that it never be granted any write permissions. In the event of a bug or a malicious attack, your code cannot damage the data on which it operates. For more information, see [Requesting Permissions](/previous-versions/dotnet/netframework-4.0/yd267cce(v=vs.100)).
|
||||
|
||||
The following example demonstrates how to use the `connectionStrings` element of a configuration file to allow only a specific connection string to be used. See [Connection Strings](connection-strings.md) for more information on storing and retrieving connection strings from configuration files.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
## Role-based security and CAS
|
||||
|
||||
Implementing both role-based security and code-accessed security (CAS) enhances overall security for your application. Role-based security can be based on a Windows account or a custom identity, making information about the security principal available to the current thread. In addition, applications are often required to provide access to data or resources based on credentials supplied by the user. Typically, such applications check the role of a user and provide access to resources based on those roles.
|
||||
|
||||
Role-based security enables a component to identify current users and their associated roles at run time. This information is then mapped using a CAS policy to determine the set of permissions granted at run time. For a specified application domain, the host can change the default role-based security policy and set a default security principal that represents a user and the roles associated with that user.
|
||||
|
||||
The CLR uses permissions to implement its mechanism for enforcing restrictions on managed code. Role-based security permissions provide a mechanism for discovering whether a user (or the agent acting on the user's behalf) has a particular identity or is a member of a specified role. For more information, see [Security Permissions](/previous-versions/dotnet/netframework-4.0/5ba4k1c5(v=vs.100)).
|
||||
|
||||
Depending on the type of application you are building, you should also consider implementing role-based permissions in the database. For more information on role-based security in SQL Server, see [SQL Server Security](/previous-versions/dotnet/framework/data/adonet/sql/sql-server-security).
|
||||
|
||||
## Assemblies
|
||||
|
||||
Assemblies form the fundamental unit of deployment, version control, reuse, activation scoping, and security permissions for a .NET Framework application. An assembly provides a collection of types and resources that are built to work together and form a logical unit of functionality. To the CLR, a type does not exist outside the context of an assembly. For more information on creating and deploying assemblies, see [Programming with Assemblies](../../../standard/assembly/index.md).
|
||||
|
||||
### Strong-named assemblies
|
||||
|
||||
A strong name, or digital signature, consists of the assembly's identity, which includes its simple text name, version number, and culture information (if provided), plus a public key and a digital signature. The digital signature is generated from an assembly file using the corresponding private key. The assembly file contains the assembly manifest, which contains the names and hashes of all the files that make up the assembly.
|
||||
|
||||
Strong naming an assembly gives an application or component a unique identity that other software can use to refer explicitly to it. Strong naming guards assemblies against being spoofed by an assembly that contains hostile code. Strong-naming also ensures versioning consistency among different versions of a component. You must strong name assemblies that will be deployed to the Global Assembly Cache (GAC). For more information, see [Creating and Using Strong-Named Assemblies](../../../standard/assembly/create-use-strong-named.md).
|
||||
|
||||
## Partial trust in ADO.NET 2.0
|
||||
|
||||
In ADO.NET 2.0, the .NET Framework Data Provider for SQL Server, the .NET Framework Data Provider for OLE DB, the .NET Framework Data Provider for ODBC, and the .NET Framework Data Provider for Oracle can now all run in partially trusted environments. In previous releases of the .NET Framework, only <xref:System.Data.SqlClient> was supported in less than full-trust applications.
|
||||
|
||||
At minimum, a partially trusted application using the SQL Server provider must have execution and <xref:System.Data.SqlClient.SqlClientPermission> permissions.
|
||||
|
||||
### Permission attribute properties for partial trust
|
||||
|
||||
For partial trust scenarios, you can use <xref:System.Data.SqlClient.SqlClientPermissionAttribute> members to further restrict the capabilities available for the .NET Framework Data Provider for SQL Server.
|
||||
|
||||
The following table lists the available <xref:System.Data.SqlClient.SqlClientPermissionAttribute> properties and their descriptions:
|
||||
|
||||
|Permission attribute property|Description|
|
||||
|-----------------------------------|-----------------|
|
||||
|`Action`|Gets or sets a security action. Inherited from <xref:System.Security.Permissions.SecurityAttribute>.|
|
||||
|`AllowBlankPassword`|Enables or disables the use of a blank password in a connection string. Valid values are `true` (to enable the use of blank passwords) and `false` (to disable the use of blank passwords). Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`ConnectionString`|Identifies a permitted connection string. Multiple connection strings can be identified. **Note:** Do not include a user ID or password in your connection string. In this release, you cannot change connection string restrictions using the .NET Framework Configuration Tool. <br /><br /> Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`KeyRestrictions`|Identifies connection string parameters that are allowed or disallowed. Connection string parameters are identified in the form *\<parameter name>=*. Multiple parameters can be specified, delimited using a semicolon (;). **Note:** If you do not specify `KeyRestrictions`, but you set `KeyRestrictionBehavior` property to `AllowOnly` or `PreventUsage`, no additional connection string parameters are allowed. Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`KeyRestrictionBehavior`|Identifies the connection string parameters as the only additional parameters allowed (`AllowOnly`), or identifies the additional parameters that are not allowed (`PreventUsage`). `AllowOnly` is the default. Inherited from <xref:System.Data.Common.DBDataPermissionAttribute>.|
|
||||
|`TypeID`|Gets a unique identifier for this attribute when implemented in a derived class. Inherited from <xref:System.Attribute>.|
|
||||
|`Unrestricted`|Indicates whether unrestricted permission to the resource is declared. Inherited from <xref:System.Security.Permissions.SecurityAttribute>.|
|
||||
|
||||
#### ConnectionString syntax
|
||||
|
||||
The following example demonstrates how to use the `connectionStrings` element of a configuration file to allow only a specific connection string to be used. For more information on storing and retrieving connection strings from configuration files, see [Connection Strings](connection-strings.md).
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="DatabaseConnection"
|
||||
connectionString="Data Source=(local);Initial
|
||||
Catalog=Northwind;Integrated Security=true;" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
#### KeyRestrictions Syntax
|
||||
Catalog=Northwind;Integrated Security=true;" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
The following example enables the same connection string, enables the use of the `Encrypt` and `Packet Size` connection string options, but restricts the use of any other connection string options.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
#### KeyRestrictions syntax
|
||||
|
||||
The following example enables the same connection string, enables the use of the `Encrypt` and `Packet Size` connection string options, but restricts the use of any other connection string options.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="DatabaseConnection"
|
||||
connectionString="Data Source=(local);Initial
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="Encrypt=;Packet Size=;"
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
#### KeyRestrictionBehavior with PreventUsage Syntax
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="Encrypt=;Packet Size=;"
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
The following example enables the same connection string and allows all other connection parameters except for `User Id`, `Password` and `Persist Security Info`.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
#### KeyRestrictionBehavior with PreventUsage syntax
|
||||
|
||||
The following example enables the same connection string and allows all other connection parameters except for `User Id`, `Password`, and `Persist Security Info`.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="DatabaseConnection"
|
||||
connectionString="Data Source=(local);Initial
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="User Id=;Password=;Persist Security Info=;"
|
||||
KeyRestrictionBehavior="PreventUsage" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
#### KeyRestrictionBehavior with AllowOnly Syntax
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="User Id=;Password=;Persist Security Info=;"
|
||||
KeyRestrictionBehavior="PreventUsage" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
The following example enables two connection strings that also contain `Initial Catalog`, `Connection Timeout`, `Encrypt`, and `Packet Size` parameters. All other connection string parameters are restricted.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
#### KeyRestrictionBehavior with AllowOnly syntax
|
||||
|
||||
The following example enables two connection strings that also contain `Initial Catalog`, `Connection Timeout`, `Encrypt`, and `Packet Size` parameters. All other connection string parameters are restricted.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="DatabaseConnection"
|
||||
connectionString="Data Source=(local);Initial
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog;Connection Timeout=;
|
||||
Catalog=Northwind;Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog;Connection Timeout=;
|
||||
Encrypt=;Packet Size=;"
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
|
||||
<add name="DatabaseConnection2"
|
||||
connectionString="Data Source=SqlServer2;Initial
|
||||
Catalog=Northwind2;Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog;Connection Timeout=;
|
||||
Catalog=Northwind2;Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog;Connection Timeout=;
|
||||
Encrypt=;Packet Size=;"
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
### Enabling Partial Trust with a Custom Permission Set
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
To enable the use of <xref:System.Data.SqlClient> permissions for a particular zone, a system administrator must create a custom permission set and set it as the permission set for a particular zone. Default permission sets, such as `LocalIntranet`, cannot be modified. For example, to include <xref:System.Data.SqlClient> permissions for code that has a <xref:System.Security.Policy.Zone> of `LocalIntranet`, a system administrator could copy the permission set for `LocalIntranet`, rename it to "CustomLocalIntranet", add the <xref:System.Data.SqlClient> permissions, import the CustomLocalIntranet permission set using the [Caspol.exe (Code Access Security Policy Tool)](../../tools/caspol-exe-code-access-security-policy-tool.md), and set the permission set of `LocalIntranet_Zone` to CustomLocalIntranet.
|
||||
|
||||
### Sample Permission Set
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
The following is a sample permission set for the .NET Framework Data Provider for SQL Server in a partially trusted scenario. For information on creating custom permission sets, see [Configuring Permission Sets Using Caspol.exe](/previous-versions/dotnet/netframework-4.0/4ybs46y6(v=vs.100)).
|
||||
|
||||
```xml
|
||||
<PermissionSet class="System.Security.NamedPermissionSet"
|
||||
version="1"
|
||||
Name="CustomLocalIntranet"
|
||||
Description="Custom permission set given to applications on
|
||||
the local intranet">
|
||||
|
||||
<IPermission class="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
||||
version="1"
|
||||
AllowBlankPassword="False">
|
||||
<add ConnectionString="Data Source=(local);Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog=;Connection Timeout=;
|
||||
### Enable partial trust with a custom permission set
|
||||
|
||||
To enable the use of <xref:System.Data.SqlClient> permissions for a particular zone, a system administrator must create a custom permission set and set it as the permission set for a particular zone. Default permission sets, such as `LocalIntranet`, cannot be modified. For example, to include <xref:System.Data.SqlClient> permissions for code that has a <xref:System.Security.Policy.Zone> of `LocalIntranet`, a system administrator could copy the permission set for `LocalIntranet`, rename it to "CustomLocalIntranet", add the <xref:System.Data.SqlClient> permissions, import the CustomLocalIntranet permission set using the [Caspol.exe (Code Access Security Policy Tool)](../../tools/caspol-exe-code-access-security-policy-tool.md), and set the permission set of `LocalIntranet_Zone` to CustomLocalIntranet.
|
||||
|
||||
### Sample permission set
|
||||
|
||||
The following is a sample permission set for the .NET Framework Data Provider for SQL Server in a partially trusted scenario. For information on creating custom permission sets, see [Configuring Permission Sets Using Caspol.exe](/previous-versions/dotnet/netframework-4.0/4ybs46y6(v=vs.100)).
|
||||
|
||||
```xml
|
||||
<PermissionSet class="System.Security.NamedPermissionSet"
|
||||
version="1"
|
||||
Name="CustomLocalIntranet"
|
||||
Description="Custom permission set given to applications on
|
||||
the local intranet">
|
||||
|
||||
<IPermission class="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
||||
version="1"
|
||||
AllowBlankPassword="False">
|
||||
<add ConnectionString="Data Source=(local);Integrated Security=true;"
|
||||
KeyRestrictions="Initial Catalog=;Connection Timeout=;
|
||||
Encrypt=;Packet Size=;"
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</IPermission>
|
||||
</PermissionSet>
|
||||
```
|
||||
|
||||
## Verifying ADO.NET Code Access Using Security Permissions
|
||||
KeyRestrictionBehavior="AllowOnly" />
|
||||
</IPermission>
|
||||
</PermissionSet>
|
||||
```
|
||||
|
||||
For partial-trust scenarios, you can require CAS privileges for particular methods in your code by specifying a <xref:System.Data.SqlClient.SqlClientPermissionAttribute>. If that privilege is not allowed by the restricted security policy in effect, an exception is thrown before your code is run. For more information on security policy, see [Security Policy Management](/previous-versions/dotnet/netframework-4.0/c1k0eed6(v=vs.100)) and [Security Policy Best Practices](/previous-versions/dotnet/netframework-4.0/sa4se9bc(v=vs.100)).
|
||||
|
||||
### Example
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## Verify ADO.NET code access using security permissions
|
||||
|
||||
For partial-trust scenarios, you can require CAS privileges for particular methods in your code by specifying a <xref:System.Data.SqlClient.SqlClientPermissionAttribute>. If that privilege is not allowed by the restricted security policy in effect, an exception is thrown before your code is run. For more information on security policy, see [Security Policy Management](/previous-versions/dotnet/netframework-4.0/c1k0eed6(v=vs.100)) and [Security Policy Best Practices](/previous-versions/dotnet/netframework-4.0/sa4se9bc(v=vs.100)).
|
||||
|
||||
### Example
|
||||
|
||||
The following example demonstrates how to write code that requires a particular connection string. It simulates denying unrestricted permissions to <xref:System.Data.SqlClient>, which a system administrator would implement using a CAS policy in the real world.
|
||||
|
||||
The following example demonstrates how to write code that requires a particular connection string. It simulates denying unrestricted permissions to <xref:System.Data.SqlClient>, which a system administrator would implement using a CAS policy in the real world.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> When designing CAS permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that are needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then denying a specific permission, is not secure because there are many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection string "server=someserver", the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are holes in the permission set.
|
||||
|
||||
The following code demonstrates how `SqlClient` performs the security demand, which throws a <xref:System.Security.SecurityException> if the appropriate CAS permissions are not in place. The <xref:System.Security.SecurityException> output is displayed in the console window.
|
||||
|
||||
[!code-csharp[DataWorks SqlClient.CAS#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks SqlClient.CAS/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks SqlClient.CAS#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks SqlClient.CAS/VB/source.vb#1)]
|
||||
|
||||
You should see this output in the Console window:
|
||||
|
||||
```output
|
||||
Failed, as expected: <IPermission class="System.Data.SqlClient.
|
||||
SqlClientPermission, System.Data, Version=2.0.0.0,
|
||||
Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"
|
||||
AllowBlankPassword="False">
|
||||
<add ConnectionString="Data Source=(local);Initial Catalog=
|
||||
Northwind;Integrated Security=SSPI" KeyRestrictions=""
|
||||
KeyRestrictionBehavior="AllowOnly"/>
|
||||
</IPermission>
|
||||
|
||||
Connection opened, as expected.
|
||||
Failed, as expected: Request failed.
|
||||
```
|
||||
|
||||
## Interoperability with Unmanaged Code
|
||||
> When designing CAS permissions for ADO.NET, the correct pattern is to start with the most restrictive case (no permissions at all) and then add the specific permissions that are needed for the particular task that the code needs to perform. The opposite pattern, starting with all permissions and then denying a specific permission, is not secure because there are many ways of expressing the same connection string. For example, if you start with all permissions and then attempt to deny the use of the connection string "server=someserver", the string "server=someserver.mycompany.com" would still be allowed. By always starting by granting no permissions at all, you reduce the chances that there are holes in the permission set.
|
||||
|
||||
The following code demonstrates how `SqlClient` performs the security demand, which throws a <xref:System.Security.SecurityException> if the appropriate CAS permissions are not in place. The <xref:System.Security.SecurityException> output is displayed in the console window.
|
||||
|
||||
[!code-csharp[DataWorks SqlClient.CAS#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks SqlClient.CAS/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks SqlClient.CAS#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks SqlClient.CAS/VB/source.vb#1)]
|
||||
|
||||
You should see this output in the Console window:
|
||||
|
||||
```output
|
||||
Failed, as expected: <IPermission class="System.Data.SqlClient.
|
||||
SqlClientPermission, System.Data, Version=2.0.0.0,
|
||||
Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1"
|
||||
AllowBlankPassword="False">
|
||||
<add ConnectionString="Data Source=(local);Initial Catalog=
|
||||
Northwind;Integrated Security=SSPI" KeyRestrictions=""
|
||||
KeyRestrictionBehavior="AllowOnly"/>
|
||||
</IPermission>
|
||||
|
||||
Connection opened, as expected.
|
||||
Failed, as expected: Request failed.
|
||||
```
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## Interoperability with unmanaged code
|
||||
|
||||
Code that runs outside the CLR is called unmanaged code. Therefore, security mechanisms such as CAS cannot be applied to unmanaged code. COM components, ActiveX interfaces, and Windows API functions are examples of unmanaged code. Special security considerations apply when executing unmanaged code so that you do not jeopardize overall application security. For more information, see [Interoperating with Unmanaged Code](../../interop/index.md).
|
||||
|
||||
.NET Framework also supports backward compatibility to existing COM components by providing access through COM interop. You can incorporate COM components into a .NET Framework application by using COM interop tools to import the relevant COM types. Once imported, the COM types are ready to use. COM interop also enables COM clients to access managed code by exporting assembly metadata to a type library and registering the managed component as a COM component. For more information, see [Advanced COM Interoperability](/previous-versions/dotnet/netframework-4.0/bd9cdfyx(v=vs.100)).
|
||||
|
||||
Code that runs outside the CLR is called unmanaged code. Therefore, security mechanisms such as CAS cannot be applied to unmanaged code. COM components, ActiveX interfaces, and Windows API functions are examples of unmanaged code. Special security considerations apply when executing unmanaged code so that you do not jeopardize overall application security. For more information, see [Interoperating with Unmanaged Code](../../interop/index.md).
|
||||
|
||||
The .NET Framework also supports backward compatibility to existing COM components by providing access through COM interop. You can incorporate COM components into a .NET Framework application by using COM interop tools to import the relevant COM types. Once imported, the COM types are ready to use. COM interop also enables COM clients to access managed code by exporting assembly metadata to a type library and registering the managed component as a COM component. For more information, see [Advanced COM Interoperability](/previous-versions/dotnet/netframework-4.0/bd9cdfyx(v=vs.100)).
|
||||
|
||||
## See also
|
||||
|
||||
- [Securing ADO.NET Applications](securing-ado-net-applications.md)
|
||||
|
|
|
@ -2,82 +2,64 @@
|
|||
title: "Connection String Builders"
|
||||
description: Learn about the connection string builder classes used for different providers in ADO.NET, all of which inherit from DbConnectionStringBuilder.
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 8434b608-c4d3-43d3-8ae3-6d8c6b726759
|
||||
---
|
||||
# Connection String Builders
|
||||
# Connection string builders
|
||||
|
||||
In earlier versions of ADO.NET, compile-time checking of connection strings with concatenated string values did not occur, so that at run time, an incorrect keyword generated an <xref:System.ArgumentException>. Each of the .NET Framework data providers supported different syntax for connection string keywords, which made constructing valid connection strings difficult if done manually. To address this problem, ADO.NET 2.0 introduced new connection string builders for each .NET Framework data provider. Each data provider includes a strongly typed connection string builder class that inherits from <xref:System.Data.Common.DbConnectionStringBuilder>. The following table lists the .NET Framework data providers and their associated connection string builder classes.
|
||||
|
||||
|Provider|ConnectionStringBuilder class|
|
||||
|--------------|-----------------------------------|
|
||||
|<xref:System.Data.SqlClient>|<xref:System.Data.SqlClient.SqlConnectionStringBuilder?displayProperty=nameWithType>|
|
||||
|<xref:System.Data.OleDb>|<xref:System.Data.OleDb.OleDbConnectionStringBuilder?displayProperty=nameWithType>|
|
||||
|<xref:System.Data.Odbc>|<xref:System.Data.Odbc.OdbcConnectionStringBuilder?displayProperty=nameWithType>|
|
||||
|<xref:System.Data.OracleClient>|<xref:System.Data.OracleClient.OracleConnectionStringBuilder?displayProperty=nameWithType>|
|
||||
|
||||
## Connection String Injection Attacks
|
||||
In early versions of ADO.NET, compile-time checking of connection strings with concatenated string values did not occur, so that at run time, an incorrect keyword generated an <xref:System.ArgumentException>. Each of the .NET Framework data providers supported different syntax for connection string keywords, which made constructing valid connection strings difficult if done manually. To address this problem, ADO.NET 2.0 introduced new connection string builders for each .NET Framework data provider. Each data provider includes a strongly typed connection string builder class that inherits from <xref:System.Data.Common.DbConnectionStringBuilder>. The following table lists the .NET Framework data providers and their associated connection string builder classes.
|
||||
|
||||
A connection string injection attack can occur when dynamic string concatenation is used to build connection strings that are based on user input. If the string is not validated and malicious text or characters not escaped, an attacker can potentially access sensitive data or other resources on the server. For example, an attacker could mount an attack by supplying a semicolon and appending an additional value. The connection string is parsed by using a "last one wins" algorithm, and the hostile input is substituted for a legitimate value.
|
||||
|
||||
The connection string builder classes are designed to eliminate guesswork and protect against syntax errors and security vulnerabilities. They provide methods and properties corresponding to the known key/value pairs permitted by each data provider. Each class maintains a fixed collection of synonyms and can translate from a synonym to the corresponding well-known key name. Checks are performed for valid key/value pairs and an invalid pair throws an exception. In addition, injected values are handled in a safe manner.
|
||||
|
||||
The following example demonstrates how the <xref:System.Data.SqlClient.SqlConnectionStringBuilder> handles an inserted extra value for the `Initial Catalog` setting.
|
||||
|
||||
```vb
|
||||
Dim builder As New System.Data.SqlClient.SqlConnectionStringBuilder
|
||||
builder("Data Source") = "(local)"
|
||||
builder("Integrated Security") = True
|
||||
builder("Initial Catalog") = "AdventureWorks;NewValue=Bad"
|
||||
Console.WriteLine(builder.ConnectionString)
|
||||
```
|
||||
|
||||
```csharp
|
||||
System.Data.SqlClient.SqlConnectionStringBuilder builder =
|
||||
new System.Data.SqlClient.SqlConnectionStringBuilder();
|
||||
builder["Data Source"] = "(local)";
|
||||
builder["integrated Security"] = true;
|
||||
builder["Initial Catalog"] = "AdventureWorks;NewValue=Bad";
|
||||
Console.WriteLine(builder.ConnectionString);
|
||||
```
|
||||
|
||||
The output shows that the <xref:System.Data.SqlClient.SqlConnectionStringBuilder> handled this correctly by escaping the extra value in double quotation marks instead of appending it to the connection string as a new key/value pair.
|
||||
|
||||
```output
|
||||
data source=(local);Integrated Security=True;
|
||||
initial catalog="AdventureWorks;NewValue=Bad"
|
||||
```
|
||||
|
||||
## Building Connection Strings from Configuration Files
|
||||
| Provider | ConnectionStringBuilder class |
|
||||
|---------------------------------|--------------------------------------------------------------------------------------------|
|
||||
| <xref:System.Data.SqlClient> | <xref:System.Data.SqlClient.SqlConnectionStringBuilder?displayProperty=nameWithType> |
|
||||
| <xref:System.Data.OleDb> | <xref:System.Data.OleDb.OleDbConnectionStringBuilder?displayProperty=nameWithType> |
|
||||
| <xref:System.Data.Odbc> | <xref:System.Data.Odbc.OdbcConnectionStringBuilder?displayProperty=nameWithType> |
|
||||
| <xref:System.Data.OracleClient> | <xref:System.Data.OracleClient.OracleConnectionStringBuilder?displayProperty=nameWithType> |
|
||||
|
||||
## Connection string injection attacks
|
||||
|
||||
A connection string injection attack can occur when dynamic string concatenation is used to build connection strings that are based on user input. If the string is not validated and malicious text or characters not escaped, an attacker can potentially access sensitive data or other resources on the server. For example, an attacker could mount an attack by supplying a semicolon and appending an additional value. The connection string is parsed by using a "last one wins" algorithm, and the hostile input is substituted for a legitimate value.
|
||||
|
||||
The connection string builder classes are designed to eliminate guesswork and protect against syntax errors and security vulnerabilities. They provide methods and properties corresponding to the known key/value pairs permitted by each data provider. Each class maintains a fixed collection of synonyms and can translate from a synonym to the corresponding well-known key name. Checks are performed for valid key/value pairs, and an invalid pair throws an exception. In addition, injected values are handled in a safe manner.
|
||||
|
||||
The following example demonstrates how <xref:System.Data.SqlClient.SqlConnectionStringBuilder> handles an inserted extra value for the `Initial Catalog` setting.
|
||||
|
||||
```vb
|
||||
Dim builder As New System.Data.SqlClient.SqlConnectionStringBuilder
|
||||
builder("Data Source") = "(local)"
|
||||
builder("Integrated Security") = True
|
||||
builder("Initial Catalog") = "AdventureWorks;NewValue=Bad"
|
||||
Console.WriteLine(builder.ConnectionString)
|
||||
```
|
||||
|
||||
```csharp
|
||||
System.Data.SqlClient.SqlConnectionStringBuilder builder =
|
||||
new System.Data.SqlClient.SqlConnectionStringBuilder();
|
||||
builder["Data Source"] = "(local)";
|
||||
builder["integrated Security"] = true;
|
||||
builder["Initial Catalog"] = "AdventureWorks;NewValue=Bad";
|
||||
Console.WriteLine(builder.ConnectionString);
|
||||
```
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
The output shows that the <xref:System.Data.SqlClient.SqlConnectionStringBuilder> handled this correctly by escaping the extra value in double quotation marks instead of appending it to the connection string as a new key/value pair.
|
||||
|
||||
```output
|
||||
data source=(local);Integrated Security=True;
|
||||
initial catalog="AdventureWorks;NewValue=Bad"
|
||||
```
|
||||
|
||||
## Build connection strings from configuration files
|
||||
|
||||
If certain elements of a connection string are known beforehand, they can be stored in a configuration file and retrieved at run time to construct a complete connection string. For example, the name of the database might be known in advance, but not the name of the server.
|
||||
|
||||
One of the overloaded constructors for a connection string builder takes a <xref:System.String> as an argument, which enables you to supply a partial connection string that can then be completed from user input. The partial connection string can be stored in a configuration file and retrieved at run time.
|
||||
|
||||
If certain elements of a connection string are known beforehand, they can be stored in a configuration file and retrieved at run time to construct a complete connection string. For example, the name of the database might be known in advance, but not the name of the server. Or you might want a user to supply a name and password at run time without being able to inject other values into the connection string.
|
||||
|
||||
One of the overloaded constructors for a connection string builder takes a <xref:System.String> as an argument, which enables you to supply a partial connection string that can then be completed from user input. The partial connection string can be stored in a configuration file and retrieved at run time.
|
||||
|
||||
> [!NOTE]
|
||||
> The <xref:System.Configuration> namespace allows programmatic access to configuration files that use the <xref:System.Web.Configuration.WebConfigurationManager> for Web applications and the <xref:System.Configuration.ConfigurationManager> for Windows applications. For more information about working with connection strings and configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
|
||||
### Example
|
||||
> The <xref:System.Configuration> namespace allows programmatic access to configuration files that use the <xref:System.Web.Configuration.WebConfigurationManager> for web apps and the <xref:System.Configuration.ConfigurationManager> for Windows applications. For more information about working with connection strings and configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
|
||||
This example demonstrates retrieving a partial connection string from a configuration file and completing it by setting the <xref:System.Data.SqlClient.SqlConnectionStringBuilder.DataSource%2A>, <xref:System.Data.SqlClient.SqlConnectionStringBuilder.UserID%2A>, and <xref:System.Data.SqlClient.SqlConnectionStringBuilder.Password%2A> properties of the <xref:System.Data.SqlClient.SqlConnectionStringBuilder>. The configuration file is defined as follows.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<clear/>
|
||||
<add name="partialConnectString"
|
||||
connectionString="Initial Catalog=Northwind;"
|
||||
providerName="System.Data.SqlClient" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You must set a reference to the `System.Configuration.dll` in your project for the code to run.
|
||||
|
||||
[!code-csharp[DataWorks SqlConnectionStringBuilder.UserNamePwd#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks SqlConnectionStringBuilder.UserNamePwd/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks SqlConnectionStringBuilder.UserNamePwd#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks SqlConnectionStringBuilder.UserNamePwd/VB/source.vb#1)]
|
||||
|
||||
## See also
|
||||
|
||||
- [Connection Strings](connection-strings.md)
|
||||
|
|
|
@ -2,212 +2,211 @@
|
|||
title: "Connection String Syntax"
|
||||
description: Learn about syntax of connection strings in ADO.NET. The syntax for each provider is documented in its ConnectionString property.
|
||||
ms.date: "05/22/2018"
|
||||
ms.assetid: 0977aeee-04d1-4cce-bbed-750c77fce06e
|
||||
---
|
||||
# Connection String Syntax
|
||||
# Connection string syntax
|
||||
|
||||
Each .NET Framework data provider has a `Connection` object that inherits from <xref:System.Data.Common.DbConnection> as well as a provider-specific <xref:System.Data.Common.DbConnection.ConnectionString%2A> property. The specific connection string syntax for each provider is documented in its `ConnectionString` property. The following table lists the four data providers that are included in the .NET Framework.
|
||||
|
||||
|.NET Framework data provider|Description|
|
||||
|----------------------------------|-----------------|
|
||||
|<xref:System.Data.SqlClient>|Provides data access for Microsoft SQL Server. For more information on connection string syntax, see <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.OleDb>|Provides data access for data sources exposed using OLE DB. For more information on connection string syntax, see <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.Odbc>|Provides data access for data sources exposed using ODBC. For more information on connection string syntax, see <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.OracleClient>|Provides data access for Oracle version 8.1.7 or later. For more information on connection string syntax, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A>.|
|
||||
|
||||
## Connection String Builders
|
||||
Each .NET Framework data provider has a `Connection` object that inherits from <xref:System.Data.Common.DbConnection> as well as a provider-specific <xref:System.Data.Common.DbConnection.ConnectionString%2A> property. The specific connection string syntax for each provider is documented in its `ConnectionString` property. The following table lists the four data providers that are included in .NET Framework.
|
||||
|
||||
ADO.NET 2.0 introduced the following connection string builders for the .NET Framework data providers.
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlConnectionStringBuilder>
|
||||
|
||||
- <xref:System.Data.OleDb.OleDbConnectionStringBuilder>
|
||||
|
||||
- <xref:System.Data.Odbc.OdbcConnectionStringBuilder>
|
||||
|
||||
- <xref:System.Data.OracleClient.OracleConnectionStringBuilder>
|
||||
|
||||
The connection string builders allow you to construct syntactically valid connection strings at run time, so you do not have to manually concatenate connection string values in your code. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
| .NET Framework data provider | Description |
|
||||
|------------------------------|-------------|
|
||||
|<xref:System.Data.SqlClient>|Provides data access for Microsoft SQL Server. For more information on connection string syntax, see <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.OleDb>|Provides data access for data sources exposed using OLE DB. For more information on connection string syntax, see <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.Odbc>|Provides data access for data sources exposed using ODBC. For more information on connection string syntax, see <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A>.|
|
||||
|<xref:System.Data.OracleClient>|Provides data access for Oracle version 8.1.7 or later. For more information on connection string syntax, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A>.|
|
||||
|
||||
## Windows Authentication
|
||||
## Connection string builders
|
||||
|
||||
ADO.NET 2.0 introduced the following connection string builders for the .NET Framework data providers.
|
||||
|
||||
- <xref:System.Data.SqlClient.SqlConnectionStringBuilder>
|
||||
- <xref:System.Data.OleDb.OleDbConnectionStringBuilder>
|
||||
- <xref:System.Data.Odbc.OdbcConnectionStringBuilder>
|
||||
- <xref:System.Data.OracleClient.OracleConnectionStringBuilder>
|
||||
|
||||
The connection string builders allow you to construct syntactically valid connection strings at run time, so you do not have to manually concatenate connection string values in your code. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
|
||||
## Windows authentication
|
||||
|
||||
Windows Authentication (sometimes referred to as *integrated security*) can be used to connect to data sources that support it. The syntax employed in the connection string varies by provider. The following table shows the Windows Authentication syntax used with the .NET Framework data providers.
|
||||
|
||||
| Provider | Syntax |
|
||||
|----------------|--------------------------------------------------------------------------------------------|
|
||||
| `SqlClient` | `Integrated Security=true;`<br /><br /> `-- or --`<br /><br /> `Integrated Security=SSPI;` |
|
||||
| `OleDb` | `Integrated Security=SSPI;` |
|
||||
| `Odbc` | `Trusted_Connection=yes;` |
|
||||
| `OracleClient` | `Integrated Security=yes;` |
|
||||
|
||||
We recommend using Windows Authentication (sometimes referred to as *integrated security*) to connect to data sources that support it. The syntax employed in the connection string varies by provider. The following table shows the Windows Authentication syntax used with the .NET Framework data providers.
|
||||
|
||||
|Provider|Syntax|
|
||||
|--------------|------------|
|
||||
|`SqlClient`|`Integrated Security=true;`<br /><br /> `-- or --`<br /><br /> `Integrated Security=SSPI;`|
|
||||
|`OleDb`|`Integrated Security=SSPI;`|
|
||||
|`Odbc`|`Trusted_Connection=yes;`|
|
||||
|`OracleClient`|`Integrated Security=yes;`|
|
||||
|
||||
> [!NOTE]
|
||||
> `Integrated Security=true` throws an exception when used with the `OleDb` provider.
|
||||
|
||||
## SqlClient Connection Strings
|
||||
> `Integrated Security=true` throws an exception when used with the `OleDb` provider.
|
||||
|
||||
The syntax for a <xref:System.Data.SqlClient.SqlConnection> connection string is documented in the <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> property. You can use the <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A> property to get or set a connection string for a SQL Server database. If you need to connect to an earlier version of SQL Server, you must use the .NET Framework Data Provider for OleDb (<xref:System.Data.OleDb>). Most connection string keywords also map to properties in the <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## SqlClient connection strings
|
||||
|
||||
The syntax for a <xref:System.Data.SqlClient.SqlConnection> connection string is documented in the <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> property. You can use the <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A> property to get or set a connection string for a SQL Server database. If you need to connect to an earlier version of SQL Server, you must use the .NET Framework Data Provider for OleDb (<xref:System.Data.OleDb>). Most connection string keywords also map to properties in the <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The default setting for the `Persist Security Info` keyword is `false`. Setting it to `true` or `yes` allows security-sensitive information, including the user ID and password, to be obtained from the connection after the connection has been opened. Keep `Persist Security Info` set to `false` to ensure that an untrusted source does not have access to sensitive connection string information.
|
||||
> The default setting for the `Persist Security Info` keyword is `false`. Setting it to `true` or `yes` allows security-sensitive information, including the user ID and password, to be obtained from the connection after the connection has been opened. Keep `Persist Security Info` set to `false` to ensure that an untrusted source does not have access to sensitive connection string information.
|
||||
|
||||
### Windows authentication with SqlClient
|
||||
|
||||
Each of the following forms of syntax uses Windows Authentication to connect to the **AdventureWorks** database on a local server.
|
||||
|
||||
```csharp
|
||||
"Persist Security Info=False;Integrated Security=true;
|
||||
Initial Catalog=AdventureWorks;Server=MSSQL1"
|
||||
"Persist Security Info=False;Integrated Security=SSPI;
|
||||
database=AdventureWorks;server=(local)"
|
||||
"Persist Security Info=False;Trusted_Connection=True;
|
||||
database=AdventureWorks;server=(local)"
|
||||
```
|
||||
|
||||
Each of the following forms of syntax uses Windows Authentication to connect to the **AdventureWorks** database on a local server.
|
||||
|
||||
```csharp
|
||||
"Persist Security Info=False;Integrated Security=true;
|
||||
Initial Catalog=AdventureWorks;Server=MSSQL1"
|
||||
"Persist Security Info=False;Integrated Security=SSPI;
|
||||
database=AdventureWorks;server=(local)"
|
||||
"Persist Security Info=False;Trusted_Connection=True;
|
||||
database=AdventureWorks;server=(local)"
|
||||
```
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### SQL Server authentication with SqlClient
|
||||
|
||||
Windows Authentication is preferred for connecting to SQL Server. However, if SQL Server Authentication is required, use the following syntax to specify a user name and password. In this example, asterisks are used to represent a valid user name and password.
|
||||
|
||||
```csharp
|
||||
"Persist Security Info=False;User ID=*****;Password=*****;Initial Catalog=AdventureWorks;Server=MySqlServer"
|
||||
```
|
||||
Windows Authentication is preferred for connecting to SQL Server (on premises). However, if SQL Server Authentication is required, use the following syntax to specify a user name and password. In this example, asterisks are used to represent a valid user name and password.
|
||||
|
||||
```csharp
|
||||
"Persist Security Info=False;User ID=*****;Password=*****;Initial Catalog=AdventureWorks;Server=MySqlServer"
|
||||
```
|
||||
|
||||
When you connect to Azure SQL Database or to Azure SQL Data Warehouse and provide a login in the format `user@servername`, make sure that the `servername` value in the login matches the value provided for `Server=`.
|
||||
|
||||
> [!NOTE]
|
||||
> Windows authentication takes precedence over SQL Server logins. If you specify both Integrated Security=true as well as a user name and password, the user name and password will be ignored and Windows authentication will be used.
|
||||
> Windows authentication takes precedence over SQL Server logins. If you specify both `Integrated Security=true` as well as a user name and password, the user name and password are ignored and Windows authentication is used.
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Connect to a named instance of SQL Server
|
||||
|
||||
To connect to a named instance of SQL Server, use the *server name\instance name* syntax.
|
||||
|
||||
```csharp
|
||||
"Data Source=MySqlServer\\MSSQL1;"
|
||||
```
|
||||
To connect to a named instance of SQL Server, use the *server name\instance name* syntax.
|
||||
|
||||
You can also set the <xref:System.Data.SqlClient.SqlConnectionStringBuilder.DataSource%2A> property of the `SqlConnectionStringBuilder` to the instance name when building a connection string. The <xref:System.Data.SqlClient.SqlConnection.DataSource%2A> property of a <xref:System.Data.SqlClient.SqlConnection> object is read-only.
|
||||
|
||||
### Type System Version Changes
|
||||
```csharp
|
||||
"Data Source=MySqlServer\\MSSQL1;"
|
||||
```
|
||||
|
||||
The `Type System Version` keyword in a <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> specifies the client-side representation of SQL Server types. See <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> for more information about the `Type System Version` keyword.
|
||||
|
||||
## Connecting and Attaching to SQL Server Express User Instances
|
||||
You can also set the <xref:System.Data.SqlClient.SqlConnectionStringBuilder.DataSource%2A> property of the `SqlConnectionStringBuilder` to the instance name when building a connection string. The <xref:System.Data.SqlClient.SqlConnection.DataSource%2A> property of a <xref:System.Data.SqlClient.SqlConnection> object is read-only.
|
||||
|
||||
User instances are a feature in SQL Server Express. They allow a user running on a least-privileged local Windows account to attach and run a SQL Server database without requiring administrative privileges. A user instance executes with the user's Windows credentials, not as a service.
|
||||
|
||||
For more information on working with user instances, see [SQL Server Express User Instances](./sql/sql-server-express-user-instances.md).
|
||||
|
||||
## Using TrustServerCertificate
|
||||
### Type system version changes
|
||||
|
||||
The `TrustServerCertificate` keyword is valid only when connecting to a SQL Server instance with a valid certificate. When `TrustServerCertificate` is set to `true`, the transport layer will use SSL to encrypt the channel and bypass walking the certificate chain to validate trust.
|
||||
|
||||
```csharp
|
||||
The `Type System Version` keyword in a <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> specifies the client-side representation of SQL Server types. See <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType> for more information about the `Type System Version` keyword.
|
||||
|
||||
## Connect and attach to SQL Server Express user instances
|
||||
|
||||
User instances are a feature in SQL Server Express. They allow a user running on a least-privileged local Windows account to attach and run a SQL Server database without requiring administrative privileges. A user instance executes with the user's Windows credentials, not as a service.
|
||||
|
||||
For more information on working with user instances, see [SQL Server Express User Instances](./sql/sql-server-express-user-instances.md).
|
||||
|
||||
## Use TrustServerCertificate
|
||||
|
||||
The `TrustServerCertificate` keyword is valid only when connecting to a SQL Server instance with a valid certificate. When `TrustServerCertificate` is set to `true`, the transport layer will use SSL to encrypt the channel and bypass walking the certificate chain to validate trust.
|
||||
|
||||
```csharp
|
||||
"TrustServerCertificate=true;"
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If `TrustServerCertificate` is set to `true` and encryption is turned on, the encryption level specified on the server will be used even if `Encrypt` is set to `false` in the connection string. The connection will fail otherwise.
|
||||
|
||||
### Enabling Encryption
|
||||
> If `TrustServerCertificate` is set to `true` and encryption is turned on, the encryption level specified on the server will be used even if `Encrypt` is set to `false` in the connection string. The connection will fail otherwise.
|
||||
|
||||
### Enable encryption
|
||||
|
||||
To enable encryption when a certificate has not been provisioned on the server, the **Force Protocol Encryption** and the **Trust Server Certificate** options must be set in SQL Server Configuration Manager. In this case, encryption will use a self-signed server certificate without validation if no verifiable certificate has been provisioned on the server.
|
||||
|
||||
Application settings cannot reduce the level of security configured in SQL Server, but can optionally strengthen it. An application can request encryption by setting the `TrustServerCertificate` and `Encrypt` keywords to `true`, guaranteeing that encryption takes place even when a server certificate has not been provisioned and **Force Protocol Encryption** has not been configured for the client. However, if `TrustServerCertificate` is not enabled in the client configuration, a provisioned server certificate is still required.
|
||||
|
||||
The following table describes all cases.
|
||||
|
||||
|Force Protocol Encryption client setting|Trust Server Certificate client setting|Encrypt/Use Encryption for Data connection string/attribute|Trust Server Certificate connection string/attribute|Result|
|
||||
|----------------------------------------------|---------------------------------------------|-------------------------------------------------------------------|-----------------------------------------------------------|------------|
|
||||
|No|N/A|No (default)|Ignored|No encryption occurs.|
|
||||
|No|N/A|Yes|No (default)|Encryption occurs only if there is a verifiable server certificate, otherwise the connection attempt fails.|
|
||||
|No|N/A|Yes|Yes|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|Yes|No|Ignored|Ignored|Encryption occurs only if there is a verifiable server certificate; otherwise, the connection attempt fails.|
|
||||
|Yes|Yes|No (default)|Ignored|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|Yes|Yes|Yes|No (default)|Encryption occurs only if there is a verifiable server certificate; otherwise, the connection attempt fails.|
|
||||
|Yes|Yes|Yes|Yes|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|
||||
To enable encryption when a certificate has not been provisioned on the server, the **Force Protocol Encryption** and the **Trust Server Certificate** options must be set in SQL Server Configuration Manager. In this case, encryption will use a self-signed server certificate without validation if no verifiable certificate has been provisioned on the server.
|
||||
|
||||
Application settings cannot reduce the level of security configured in SQL Server, but can optionally strengthen it. An application can request encryption by setting the `TrustServerCertificate` and `Encrypt` keywords to `true`, guaranteeing that encryption takes place even when a server certificate has not been provisioned and **Force Protocol Encryption** has not been configured for the client. However, if `TrustServerCertificate` is not enabled in the client configuration, a provisioned server certificate is still required.
|
||||
|
||||
The following table describes all cases.
|
||||
|
||||
|Force Protocol Encryption client setting|Trust Server Certificate client setting|Encrypt/Use Encryption for Data connection string/attribute|Trust Server Certificate connection string/attribute|Result|
|
||||
|----------------------------------------------|---------------------------------------------|-------------------------------------------------------------------|-----------------------------------------------------------|------------|
|
||||
|No|N/A|No (default)|Ignored|No encryption occurs.|
|
||||
|No|N/A|Yes|No (default)|Encryption occurs only if there is a verifiable server certificate, otherwise the connection attempt fails.|
|
||||
|No|N/A|Yes|Yes|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|Yes|No|Ignored|Ignored|Encryption occurs only if there is a verifiable server certificate; otherwise, the connection attempt fails.|
|
||||
|Yes|Yes|No (default)|Ignored|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|Yes|Yes|Yes|No (default)|Encryption occurs only if there is a verifiable server certificate; otherwise, the connection attempt fails.|
|
||||
|Yes|Yes|Yes|Yes|Encryption always occurs, but may use a self-signed server certificate.|
|
||||
|
||||
For more information, see [Using Encryption Without Validation](/sql/relational-databases/native-client/features/using-encryption-without-validation).
|
||||
|
||||
## OleDb Connection Strings
|
||||
|
||||
The <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A> property of a <xref:System.Data.OleDb.OleDbConnection> allows you to get or set a connection string for an OLE DB data source, such as Microsoft Access. You can also create an `OleDb` connection string at run time by using the <xref:System.Data.OleDb.OleDbConnectionStringBuilder> class.
|
||||
|
||||
### OleDb Connection String Syntax
|
||||
## OleDb connection strings
|
||||
|
||||
The <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A> property of a <xref:System.Data.OleDb.OleDbConnection> allows you to get or set a connection string for an OLE DB data source, such as Microsoft Access. You can also create an `OleDb` connection string at run time by using the <xref:System.Data.OleDb.OleDbConnectionStringBuilder> class.
|
||||
|
||||
### OleDb connection string syntax
|
||||
|
||||
You must specify a provider name for an <xref:System.Data.OleDb.OleDbConnection> connection string. The following connection string connects to a Microsoft Access database using the Jet provider. Note that the `User ID` and `Password` keywords are optional if the database is unsecured (the default).
|
||||
|
||||
You must specify a provider name for an <xref:System.Data.OleDb.OleDbConnection> connection string. The following connection string connects to a Microsoft Access database using the Jet provider. Note that the `User ID` and `Password` keywords are optional if the database is unsecured (the default).
|
||||
|
||||
```csharp
|
||||
Provider=Microsoft.Jet.OLEDB.4.0; Data Source=d:\Northwind.mdb;User ID=Admin;Password=;
|
||||
```
|
||||
|
||||
If the Jet database is secured using user-level security, you must provide the location of the workgroup information file (.mdw). The workgroup information file is used to validate the credentials presented in the connection string.
|
||||
|
||||
```
|
||||
|
||||
If the Jet database is secured using user-level security, you must provide the location of the workgroup information file (.mdw). The workgroup information file is used to validate the credentials presented in the connection string.
|
||||
|
||||
```csharp
|
||||
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\Northwind.mdb;Jet OLEDB:System Database=d:\NorthwindSystem.mdw;User ID=*****;Password=*****;
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> It is possible to supply connection information for an **OleDbConnection** in a Universal Data Link (UDL) file; however you should avoid doing so. UDL files are not encrypted, and expose connection string information in clear text. Because a UDL file is an external file-based resource to your application, it cannot be secured using the .NET Framework. UDL files are not supported for **SqlClient**.
|
||||
|
||||
### Using DataDirectory to Connect to Access/Jet
|
||||
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\Northwind.mdb;Jet OLEDB:System Database=d:\NorthwindSystem.mdw;User ID=*****;Password=*****;
|
||||
```
|
||||
|
||||
`DataDirectory` is not exclusive to `SqlClient`. It can also be used with the <xref:System.Data.OleDb> and <xref:System.Data.Odbc> .NET data providers. The following sample <xref:System.Data.OleDb.OleDbConnection> string demonstrates the syntax required to connect to the Northwind.mdb located in the application's app_data folder. The system database (System.mdw) is also stored in that location.
|
||||
|
||||
```csharp
|
||||
"Provider=Microsoft.Jet.OLEDB.4.0;
|
||||
Data Source=|DataDirectory|\Northwind.mdb;
|
||||
Jet OLEDB:System Database=|DataDirectory|\System.mdw;"
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Specifying the location of the system database in the connection string is not required if the Access/Jet database is unsecured. Security is off by default, with all users connecting as the built-in Admin user with a blank password. Even when user-level security is correctly implemented, a Jet database remains vulnerable to attack. Therefore, storing sensitive information in an Access/Jet database is not recommended because of the inherent weakness of its file-based security scheme.
|
||||
|
||||
### Connecting to Excel
|
||||
> It is possible to supply connection information for an **OleDbConnection** in a Universal Data Link (UDL) file; however you should avoid doing so. UDL files are not encrypted, and expose connection string information in clear text. Because a UDL file is an external file-based resource to your application, it cannot be secured using .NET Framework. UDL files are not supported for **SqlClient**.
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Use DataDirectory to connect to Access/Jet
|
||||
|
||||
`DataDirectory` is not exclusive to `SqlClient`. It can also be used with the <xref:System.Data.OleDb> and <xref:System.Data.Odbc> .NET data providers. The following sample <xref:System.Data.OleDb.OleDbConnection> string demonstrates the syntax required to connect to the Northwind.mdb located in the application's app_data folder. The system database (System.mdw) is also stored in that location.
|
||||
|
||||
The Microsoft Jet provider is used to connect to an Excel workbook. In the following connection string, the `Extended Properties` keyword sets properties that are specific to Excel. "HDR=Yes;" indicates that the first row contains column names, not data, and "IMEX=1;" tells the driver to always read "intermixed" data columns as text.
|
||||
|
||||
```csharp
|
||||
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\MyExcel.xls;Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""
|
||||
```
|
||||
|
||||
Note that the double quotation character required for the `Extended Properties` must also be enclosed in double quotation marks.
|
||||
|
||||
### Data Shape Provider Connection String Syntax
|
||||
"Provider=Microsoft.Jet.OLEDB.4.0;
|
||||
Data Source=|DataDirectory|\Northwind.mdb;
|
||||
Jet OLEDB:System Database=|DataDirectory|\System.mdw;"
|
||||
```
|
||||
|
||||
Use both the `Provider` and the `Data Provider` keywords when using the Microsoft Data Shape provider. The following example uses the Shape provider to connect to a local instance of SQL Server.
|
||||
|
||||
```csharp
|
||||
> [!IMPORTANT]
|
||||
> Specifying the location of the system database in the connection string is not required if the Access/Jet database is unsecured. Security is off by default, with all users connecting as the built-in Admin user with a blank password. Even when user-level security is correctly implemented, a Jet database remains vulnerable to attack. Therefore, storing sensitive information in an Access/Jet database is not recommended because of the inherent weakness of its file-based security scheme.
|
||||
|
||||
### Connect to Excel
|
||||
|
||||
The Microsoft Jet provider is used to connect to an Excel workbook. In the following connection string, the `Extended Properties` keyword sets properties that are specific to Excel. "HDR=Yes;" indicates that the first row contains column names, not data, and "IMEX=1;" tells the driver to always read "intermixed" data columns as text.
|
||||
|
||||
```csharp
|
||||
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\MyExcel.xls;Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""
|
||||
```
|
||||
|
||||
Note that the double quotation character required for the `Extended Properties` must also be enclosed in double quotation marks.
|
||||
|
||||
### Data Shape provider connection string syntax
|
||||
|
||||
Use both the `Provider` and the `Data Provider` keywords when using the Microsoft Data Shape provider. The following example uses the Shape provider to connect to a local instance of SQL Server.
|
||||
|
||||
```csharp
|
||||
"Provider=MSDataShape;Data Provider=SQLOLEDB;Data Source=(local);Initial Catalog=pubs;Integrated Security=SSPI;"
|
||||
```
|
||||
|
||||
## Odbc Connection Strings
|
||||
```
|
||||
|
||||
The <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A> property of a <xref:System.Data.Odbc.OdbcConnection> allows you to get or set a connection string for an OLE DB data source. Odbc connection strings are also supported by the <xref:System.Data.Odbc.OdbcConnectionStringBuilder>.
|
||||
|
||||
The following connection string uses the Microsoft Text Driver.
|
||||
|
||||
```csharp
|
||||
Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=d:\bin
|
||||
```
|
||||
|
||||
### Using DataDirectory to Connect to Visual FoxPro
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
The following <xref:System.Data.Odbc.OdbcConnection> connection string sample demonstrates using `DataDirectory` to connect to a Microsoft Visual FoxPro file.
|
||||
|
||||
```csharp
|
||||
"Driver={Microsoft Visual FoxPro Driver};
|
||||
SourceDB=|DataDirectory|\MyData.DBC;SourceType=DBC;"
|
||||
```
|
||||
|
||||
## Oracle Connection Strings
|
||||
## Odbc connection strings
|
||||
|
||||
The <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A> property of a <xref:System.Data.Odbc.OdbcConnection> allows you to get or set a connection string for an OLE DB data source. Odbc connection strings are also supported by the <xref:System.Data.Odbc.OdbcConnectionStringBuilder>.
|
||||
|
||||
The following connection string uses the Microsoft Text Driver.
|
||||
|
||||
The <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A> property of a <xref:System.Data.OracleClient.OracleConnection> allows you to get or set a connection string for an OLE DB data source. Oracle connection strings are also supported by the <xref:System.Data.OracleClient.OracleConnectionStringBuilder> .
|
||||
|
||||
```csharp
|
||||
Data Source=Oracle9i;User ID=*****;Password=*****;
|
||||
```
|
||||
|
||||
For more information on ODBC connection string syntax, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A>.
|
||||
|
||||
Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=d:\bin
|
||||
```
|
||||
|
||||
## Oracle connection strings
|
||||
|
||||
The <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A> property of a <xref:System.Data.OracleClient.OracleConnection> allows you to get or set a connection string for an OLE DB data source. Oracle connection strings are also supported by the <xref:System.Data.OracleClient.OracleConnectionStringBuilder> .
|
||||
|
||||
```csharp
|
||||
Data Source=Oracle9i;User ID=*****;Password=*****;
|
||||
```
|
||||
|
||||
For more information on ODBC connection string syntax, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A>.
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## See also
|
||||
|
||||
- [Connection Strings](connection-strings.md)
|
||||
|
|
|
@ -1,183 +1,182 @@
|
|||
---
|
||||
title: "Connection Strings and Configuration Files"
|
||||
description: Learn how to store connection strings for ADO.NET applications in an application configuration file, as a best practice for security and maintenance.
|
||||
description: Learn how to store connection strings for ADO.NET applications in an application configuration file.
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 37df2641-661e-407a-a3fb-7bf9540f01e8
|
||||
---
|
||||
# Connection Strings and Configuration Files
|
||||
# Connection strings and configuration files
|
||||
|
||||
Embedding connection strings in your application's code can lead to security vulnerabilities and maintenance problems. Unencrypted connection strings compiled into an application's source code can be viewed using the [Ildasm.exe (IL Disassembler)](../../tools/ildasm-exe-il-disassembler.md) tool. Moreover, if the connection string ever changes, your application must be recompiled. For these reasons, we recommend storing connection strings in an application configuration file.
|
||||
|
||||
## Working with Application Configuration Files
|
||||
Embedding connection strings in your application's code can lead to security vulnerabilities and maintenance problems. Unencrypted connection strings compiled into an application's source code can be viewed using the [Ildasm.exe (IL Disassembler)](../../tools/ildasm-exe-il-disassembler.md) tool. Moreover, if the connection string ever changes, your application must be recompiled. For these reasons, we recommend storing connection strings in an application configuration file.
|
||||
|
||||
Application configuration files contain settings that are specific to a particular application. For example, an ASP.NET application can have one or more **web.config** files, and a Windows application can have an optional **app.config** file. Configuration files share common elements, although the name and location of a configuration file vary depending on the application's host.
|
||||
|
||||
### The connectionStrings Section
|
||||
## Working with Application Configuration Files
|
||||
|
||||
Connection strings can be stored as key/value pairs in the **connectionStrings** section of the **configuration** element of an application configuration file. Child elements include **add**, **clear**, and **remove**.
|
||||
|
||||
The following configuration file fragment demonstrates the schema and syntax for storing a connection string. The **name** attribute is a name that you provide to uniquely identify a connection string so that it can be retrieved at run time. The **providerName** is the invariant name of the .NET Framework data provider, which is registered in the machine.config file.
|
||||
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<configuration>
|
||||
<connectionStrings>
|
||||
<clear />
|
||||
Application configuration files contain settings that are specific to a particular application. For example, an ASP.NET application can have one or more **web.config** files, and a Windows application can have an optional **app.config** file. Configuration files share common elements, although the name and location of a configuration file vary depending on the application's host.
|
||||
|
||||
### The connectionStrings Section
|
||||
|
||||
Connection strings can be stored as key/value pairs in the **connectionStrings** section of the **configuration** element of an application configuration file. Child elements include **add**, **clear**, and **remove**.
|
||||
|
||||
The following configuration file fragment demonstrates the schema and syntax for storing a connection string. The **name** attribute is a name that you provide to uniquely identify a connection string so that it can be retrieved at run time. The **providerName** is the invariant name of the .NET Framework data provider, which is registered in the machine.config file.
|
||||
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<configuration>
|
||||
<connectionStrings>
|
||||
<clear />
|
||||
<add name="Name"
|
||||
providerName="System.Data.ProviderName"
|
||||
connectionString="Valid Connection String;" />
|
||||
</connectionStrings>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You can save part of a connection string in a configuration file and use the <xref:System.Data.Common.DbConnectionStringBuilder> class to complete it at run time. This is useful in scenarios where you do not know elements of the connection string ahead of time, or when you do not want to save sensitive information in a configuration file. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
|
||||
### Using External Configuration Files
|
||||
connectionString="Valid Connection String;" />
|
||||
</connectionStrings>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
External configuration files are separate files that contain a fragment of a configuration file consisting of a single section. The external configuration file is then referenced by the main configuration file. Storing the **connectionStrings** section in a physically separate file is useful in situations where connection strings may be edited after the application is deployed. For example, the standard ASP.NET behavior is to restart an application domain when configuration files are modified, which results in state information being lost. However, modifying an external configuration file does not cause an application restart. External configuration files are not limited to ASP.NET; they can also be used by Windows applications. In addition, file access security and permissions can be used to restrict access to external configuration files. Working with external configuration files at run time is transparent, and requires no special coding.
|
||||
|
||||
To store connection strings in an external configuration file, create a separate file that contains only the **connectionStrings** section. Do not include any additional elements, sections, or attributes. This example shows the syntax for an external configuration file.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
> [!NOTE]
|
||||
> You can save part of a connection string in a configuration file and use the <xref:System.Data.Common.DbConnectionStringBuilder> class to complete it at run time. This is useful in scenarios where you do not know elements of the connection string ahead of time, or when you don't want to save sensitive information in a configuration file. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
|
||||
### Use External Configuration Files
|
||||
|
||||
External configuration files are separate files that contain a fragment of a configuration file consisting of a single section. The external configuration file is then referenced by the main configuration file. Storing the **connectionStrings** section in a physically separate file is useful in situations where connection strings might be edited after the application is deployed. For example, the standard ASP.NET behavior is to restart an application domain when configuration files are modified, which results in state information being lost. However, modifying an external configuration file does not cause an application restart. External configuration files are not limited to ASP.NET; they can also be used by Windows applications. In addition, file access security and permissions can be used to restrict access to external configuration files. Working with external configuration files at run time is transparent, and requires no special coding.
|
||||
|
||||
To store connection strings in an external configuration file, create a separate file that contains only the **connectionStrings** section. Do not include any additional elements, sections, or attributes. This example shows the syntax for an external configuration file.
|
||||
|
||||
```xml
|
||||
<connectionStrings>
|
||||
<add name="Name"
|
||||
providerName="System.Data.ProviderName"
|
||||
connectionString="Valid Connection String;" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
In the main application configuration file, you use the **configSource** attribute to specify the fully qualified name and location of the external file. This example refers to an external configuration file named `connections.config`.
|
||||
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<configuration>
|
||||
<connectionStrings configSource="connections.config"/>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
## Retrieving Connection Strings at Run Time
|
||||
connectionString="Valid Connection String;" />
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
The .NET Framework 2.0 introduced new classes in the <xref:System.Configuration> namespace to simplify retrieving connection strings from configuration files at run time. You can programmatically retrieve a connection string by name or by provider name.
|
||||
|
||||
> [!NOTE]
|
||||
> The **machine.config** file also contains a **connectionStrings** section, which contains connection strings used by Visual Studio. When retrieving connection strings by provider name from the **app.config** file in a Windows application, the connection strings in **machine.config** get loaded first, and then the entries from **app.config**. Adding **clear** immediately after the **connectionStrings** element removes all inherited references from the data structure in memory, so that only the connection strings defined in the local **app.config** file are considered.
|
||||
|
||||
### Working with the Configuration Classes
|
||||
In the main application configuration file, you use the **configSource** attribute to specify the fully qualified name and location of the external file. This example refers to an external configuration file named `connections.config`.
|
||||
|
||||
Starting with .NET Framework 2.0, <xref:System.Configuration.ConfigurationManager> is used when working with configuration files on the local computer, replacing the deprecated <xref:System.Configuration.ConfigurationSettings>. <xref:System.Web.Configuration.WebConfigurationManager> is used to work with ASP.NET configuration files. It is designed to work with configuration files on a Web server, and allows programmatic access to configuration file sections such as **system.web**.
|
||||
|
||||
> [!NOTE]
|
||||
> Accessing configuration files at run time requires granting permissions to the caller; the required permissions depend on the type of application, configuration file, and location. For more information, see [Using the Configuration Classes](/previous-versions/aspnet/ms228063(v=vs.100)) and <xref:System.Web.Configuration.WebConfigurationManager> for ASP.NET applications, and <xref:System.Configuration.ConfigurationManager> for Windows applications.
|
||||
|
||||
You can use the <xref:System.Configuration.ConnectionStringSettingsCollection> to retrieve connection strings from application configuration files. It contains a collection of <xref:System.Configuration.ConnectionStringSettings> objects, each of which represents a single entry in the **connectionStrings** section. Its properties map to connection string attributes, allowing you to retrieve a connection string by specifying the name or the provider name.
|
||||
|
||||
|Property|Description|
|
||||
|--------------|-----------------|
|
||||
|<xref:System.Configuration.ConnectionStringSettings.Name%2A>|The name of the connection string. Maps to the **name** attribute.|
|
||||
|<xref:System.Configuration.ConnectionStringSettings.ProviderName%2A>|The fully qualified provider name. Maps to the **providerName** attribute.|
|
||||
|<xref:System.Configuration.ConnectionStringSettings.ConnectionString%2A>|The connection string. Maps to the **connectionString** attribute.|
|
||||
|
||||
### Example: Listing All Connection Strings
|
||||
```xml
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<configuration>
|
||||
<connectionStrings configSource="connections.config"/>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
## Retrieve Connection Strings at Run Time
|
||||
|
||||
.NET Framework 2.0 introduced new classes in the <xref:System.Configuration> namespace to simplify retrieving connection strings from configuration files at run time. You can programmatically retrieve a connection string by name or by provider name.
|
||||
|
||||
This example iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection> and displays the <xref:System.Configuration.ConnectionStringSettings.Name%2A?displayProperty=nameWithType>, <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A?displayProperty=nameWithType>, and <xref:System.Configuration.ConnectionStringSettings.ConnectionString%2A?displayProperty=nameWithType> properties in the console window.
|
||||
|
||||
> [!NOTE]
|
||||
> System.Configuration.dll is not included in all project types, and you may need to set a reference to it in order to use the configuration classes. The name and location of a particular application configuration file varies by the type of application and the hosting process.
|
||||
|
||||
> The **machine.config** file also contains a **connectionStrings** section, which contains connection strings used by Visual Studio. When retrieving connection strings by provider name from the **app.config** file in a Windows application, the connection strings in **machine.config** get loaded first, and then the entries from **app.config**. Adding **clear** immediately after the **connectionStrings** element removes all inherited references from the data structure in memory, so that only the connection strings defined in the local **app.config** file are considered.
|
||||
|
||||
### Work with the Configuration Classes
|
||||
|
||||
Starting with .NET Framework 2.0, <xref:System.Configuration.ConfigurationManager> is used when working with configuration files on the local computer, replacing the deprecated <xref:System.Configuration.ConfigurationSettings> class. <xref:System.Web.Configuration.WebConfigurationManager> is used to work with ASP.NET configuration files. It is designed to work with configuration files on a Web server, and allows programmatic access to configuration file sections such as **system.web**.
|
||||
|
||||
> [!NOTE]
|
||||
> Accessing configuration files at run time requires granting permissions to the caller; the required permissions depend on the type of application, configuration file, and location. For more information, see [Using the Configuration Classes](/previous-versions/aspnet/ms228063(v=vs.100)) and <xref:System.Web.Configuration.WebConfigurationManager> for ASP.NET applications, and <xref:System.Configuration.ConfigurationManager> for Windows applications.
|
||||
|
||||
You can use the <xref:System.Configuration.ConnectionStringSettingsCollection> to retrieve connection strings from application configuration files. It contains a collection of <xref:System.Configuration.ConnectionStringSettings> objects, each of which represents a single entry in the **connectionStrings** section. Its properties map to connection string attributes, allowing you to retrieve a connection string by specifying the name or the provider name.
|
||||
|
||||
| Property | Description |
|
||||
|--------------------------------------------------------------|--------------------------------------------------------------------|
|
||||
| <xref:System.Configuration.ConnectionStringSettings.Name%2A> | The name of the connection string. Maps to the **name** attribute. |
|
||||
|<xref:System.Configuration.ConnectionStringSettings.ProviderName%2A>|The fully qualified provider name. Maps to the **providerName** attribute.|
|
||||
|<xref:System.Configuration.ConnectionStringSettings.ConnectionString%2A>|The connection string. Maps to the **connectionString** attribute.|
|
||||
|
||||
### Example: List All Connection Strings
|
||||
|
||||
This example iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection> and displays the <xref:System.Configuration.ConnectionStringSettings.Name%2A?displayProperty=nameWithType>, <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A?displayProperty=nameWithType>, and <xref:System.Configuration.ConnectionStringSettings.ConnectionString%2A?displayProperty=nameWithType> properties in the console window.
|
||||
|
||||
> [!NOTE]
|
||||
> System.Configuration.dll is not included in all project types, and you might need to set a reference to it in order to use the configuration classes. The name and location of a particular application configuration file varies by the type of application and the hosting process.
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringSettings.RetrieveFromConfig#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfig/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfig#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfig/VB/source.vb#1)]
|
||||
|
||||
### Example: Retrieving a Connection String by Name
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfig#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfig/VB/source.vb#1)]
|
||||
|
||||
### Example: Retrieve a Connection String by Name
|
||||
|
||||
This example demonstrates how to retrieve a connection string from a configuration file by specifying its name. The code creates a <xref:System.Configuration.ConnectionStringSettings> object, matching the supplied input parameter to the <xref:System.Configuration.ConfigurationManager.ConnectionStrings%2A> name. If no matching name is found, the function returns `null` (`Nothing` in Visual Basic).
|
||||
|
||||
This example demonstrates how to retrieve a connection string from a configuration file by specifying its name. The code creates a <xref:System.Configuration.ConnectionStringSettings> object, matching the supplied input parameter to the <xref:System.Configuration.ConfigurationManager.ConnectionStrings%2A> name. If no matching name is found, the function returns `null` (`Nothing` in Visual Basic).
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringSettings.RetrieveFromConfigByName#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByName/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByName#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByName/VB/source.vb#1)]
|
||||
|
||||
### Example: Retrieving a Connection String by Provider Name
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByName#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByName/VB/source.vb#1)]
|
||||
|
||||
### Example: Retrieve a Connection String by Provider Name
|
||||
|
||||
This example demonstrates how to retrieve a connection string by specifying the provider-invariant name in the format *System.Data.ProviderName*. The code iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection> and returns the connection string for the first <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A> found. If the provider name is not found, the function returns `null` (`Nothing` in Visual Basic).
|
||||
|
||||
This example demonstrates how to retrieve a connection string by specifying the provider-invariant name in the format *System.Data.ProviderName*. The code iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection> and returns the connection string for the first <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A> found. If the provider name is not found, the function returns `null` (`Nothing` in Visual Basic).
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/VB/source.vb#1)]
|
||||
|
||||
## Encrypting Configuration File Sections Using Protected Configuration
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/VB/source.vb#1)]
|
||||
|
||||
ASP.NET 2.0 introduced a new feature, called *protected configuration*, that enables you to encrypt sensitive information in a configuration file. Although primarily designed for ASP.NET, protected configuration can also be used to encrypt configuration file sections in Windows applications. For a detailed description of the protected configuration capabilities, see [Encrypting Configuration Information Using Protected Configuration](/previous-versions/aspnet/53tyfkaw(v=vs.100)).
|
||||
|
||||
The following configuration file fragment shows the **connectionStrings** section after it has been encrypted. The **configProtectionProvider** specifies the protected configuration provider used to encrypt and decrypt the connection strings. The **EncryptedData** section contains the cipher text.
|
||||
|
||||
```xml
|
||||
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
|
||||
<EncryptedData>
|
||||
<CipherData>
|
||||
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAH2... </CipherValue>
|
||||
</CipherData>
|
||||
</EncryptedData>
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
When the encrypted connection string is retrieved at run time, the .NET Framework uses the specified provider to decrypt the **CipherValue** and make it available to your application. You do not need to write any additional code to manage the decryption process.
|
||||
|
||||
### Protected Configuration Providers
|
||||
## Encrypt Configuration File Sections Using Protected Configuration
|
||||
|
||||
Protected configuration providers are registered in the **configProtectedData** section of the **machine.config** file on the local computer, as shown in the following fragment, which shows the two protected configuration providers supplied with the .NET Framework. The values shown here have been truncated for readability.
|
||||
|
||||
```xml
|
||||
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
|
||||
<providers>
|
||||
ASP.NET 2.0 introduced a new feature, called *protected configuration*, that enables you to encrypt sensitive information in a configuration file. Although primarily designed for ASP.NET, protected configuration can also be used to encrypt configuration file sections in Windows applications. For a detailed description of the protected configuration capabilities, see [Encrypting Configuration Information Using Protected Configuration](/previous-versions/aspnet/53tyfkaw(v=vs.100)).
|
||||
|
||||
The following configuration file fragment shows the **connectionStrings** section after it has been encrypted. The **configProtectionProvider** specifies the protected configuration provider used to encrypt and decrypt the connection strings. The **EncryptedData** section contains the cipher text.
|
||||
|
||||
```xml
|
||||
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
|
||||
<EncryptedData>
|
||||
<CipherData>
|
||||
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAH2... </CipherValue>
|
||||
</CipherData>
|
||||
</EncryptedData>
|
||||
</connectionStrings>
|
||||
```
|
||||
|
||||
When the encrypted connection string is retrieved at run time, .NET Framework uses the specified provider to decrypt the **CipherValue** and make it available to your application. You do not need to write any additional code to manage the decryption process.
|
||||
|
||||
### Protected Configuration Providers
|
||||
|
||||
Protected configuration providers are registered in the **configProtectedData** section of the **machine.config** file on the local computer, as shown in the following fragment, which shows the two protected configuration providers supplied with .NET Framework. The values shown here have been truncated for readability.
|
||||
|
||||
```xml
|
||||
<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">
|
||||
<providers>
|
||||
<add name="RsaProtectedConfigurationProvider"
|
||||
type="System.Configuration.RsaProtectedConfigurationProvider" />
|
||||
type="System.Configuration.RsaProtectedConfigurationProvider" />
|
||||
<add name="DataProtectionConfigurationProvider"
|
||||
type="System.Configuration.DpapiProtectedConfigurationProvider" />
|
||||
</providers>
|
||||
</configProtectedData>
|
||||
```
|
||||
|
||||
You can configure additional protected configuration providers by adding them to the **machine.config** file. You can also create your own protected configuration provider by inheriting from the <xref:System.Configuration.ProtectedConfigurationProvider> abstract base class. The following table describes the two configuration files included with the .NET Framework.
|
||||
|
||||
|Provider|Description|
|
||||
|--------------|-----------------|
|
||||
|<xref:System.Configuration.RsaProtectedConfigurationProvider>|Uses the RSA encryption algorithm to encrypt and decrypt data. The RSA algorithm can be used for both public key encryption and digital signatures. It is also known as "public key" or asymmetrical encryption because it employs two different keys. You can use the [ASP.NET IIS Registration Tool (Aspnet_regiis.exe)](/previous-versions/dotnet/netframework-3.5/k6h9cz8h(v=vs.90)) to encrypt sections in a Web.config file and manage the encryption keys. ASP.NET decrypts the configuration file when it processes the file. The identity of the ASP.NET application must have read access to the encryption key that is used to encrypt and decrypt the encrypted sections.|
|
||||
|<xref:System.Configuration.DpapiProtectedConfigurationProvider>|Uses the Windows Data Protection API (DPAPI) to encrypt configuration sections. It uses the Windows built-in cryptographic services and can be configured for either machine-specific or user-account-specific protection. Machine-specific protection is useful for multiple applications on the same server that need to share information. User-account-specific protection can be used with services that run with a specific user identity, such as a shared hosting environment. Each application runs under a separate identity which restricts access to resources such as files and databases.|
|
||||
|
||||
Both providers offer strong encryption of data. However, if you are planning to use the same encrypted configuration file on multiple servers, such as a Web farm, only the <xref:System.Configuration.RsaProtectedConfigurationProvider> enables you to export the encryption keys used to encrypt the data and import them on another server. For more information, see [Importing and Exporting Protected Configuration RSA Key Containers](/previous-versions/aspnet/yxw286t2(v=vs.100)).
|
||||
|
||||
### Using the Configuration Classes
|
||||
type="System.Configuration.DpapiProtectedConfigurationProvider" />
|
||||
</providers>
|
||||
</configProtectedData>
|
||||
```
|
||||
|
||||
The <xref:System.Configuration> namespace provides classes to work with configuration settings programmatically. The <xref:System.Configuration.ConfigurationManager> class provides access to machine, application, and user configuration files. If you are creating an ASP.NET application, you can use the <xref:System.Web.Configuration.WebConfigurationManager> class, which provides the same functionality while also allowing you to access settings that are unique to ASP.NET applications, such as those found in **\<system.web>**.
|
||||
|
||||
> [!NOTE]
|
||||
> The <xref:System.Security.Cryptography> namespace contains classes that provide additional options for encrypting and decrypting data. Use these classes if you require cryptographic services that are not available using protected configuration. Some of these classes are wrappers for the unmanaged Microsoft CryptoAPI, while others are purely managed implementations. For more information, see [Cryptographic Services](/previous-versions/visualstudio/visual-studio-2008/93bskf9z(v=vs.90)).
|
||||
|
||||
### App.config Example
|
||||
You can configure additional protected configuration providers by adding them to the **machine.config** file. You can also create your own protected configuration provider by inheriting from the <xref:System.Configuration.ProtectedConfigurationProvider> abstract base class. The following table describes the two configuration files included with .NET Framework.
|
||||
|
||||
| Provider | Description |
|
||||
|----------|-------------|
|
||||
|<xref:System.Configuration.RsaProtectedConfigurationProvider>|Uses the RSA encryption algorithm to encrypt and decrypt data. The RSA algorithm can be used for both public key encryption and digital signatures. It is also known as "public key" or asymmetrical encryption because it employs two different keys. You can use the [ASP.NET IIS Registration Tool (Aspnet_regiis.exe)](/previous-versions/dotnet/netframework-3.5/k6h9cz8h(v=vs.90)) to encrypt sections in a Web.config file and manage the encryption keys. ASP.NET decrypts the configuration file when it processes the file. The identity of the ASP.NET application must have read access to the encryption key that is used to encrypt and decrypt the encrypted sections.|
|
||||
|<xref:System.Configuration.DpapiProtectedConfigurationProvider>|Uses the Windows Data Protection API (DPAPI) to encrypt configuration sections. It uses the Windows built-in cryptographic services and can be configured for either machine-specific or user-account-specific protection. Machine-specific protection is useful for multiple applications on the same server that need to share information. User-account-specific protection can be used with services that run with a specific user identity, such as a shared hosting environment. Each application runs under a separate identity which restricts access to resources such as files and databases.|
|
||||
|
||||
Both providers offer strong encryption of data. However, if you are planning to use the same encrypted configuration file on multiple servers, such as a Web farm, only the <xref:System.Configuration.RsaProtectedConfigurationProvider> enables you to export the encryption keys used to encrypt the data and import them on another server. For more information, see [Importing and Exporting Protected Configuration RSA Key Containers](/previous-versions/aspnet/yxw286t2(v=vs.100)).
|
||||
|
||||
### Use the Configuration Classes
|
||||
|
||||
The <xref:System.Configuration> namespace provides classes to work with configuration settings programmatically. The <xref:System.Configuration.ConfigurationManager> class provides access to machine, application, and user configuration files. If you are creating an ASP.NET application, you can use the <xref:System.Web.Configuration.WebConfigurationManager> class, which provides the same functionality while also allowing you to access settings that are unique to ASP.NET applications, such as those found in **\<system.web>**.
|
||||
|
||||
This example demonstrates how to toggle encrypting the **connectionStrings** section in an **app.config** file for a Windows application. In this example, the procedure takes the name of the application as an argument, for example, "MyApplication.exe". The **app.config** file will then be encrypted and copied to the folder that contains the executable under the name of "MyApplication.exe.config".
|
||||
|
||||
> [!NOTE]
|
||||
> The connection string can only be decrypted on the computer on which it was encrypted.
|
||||
|
||||
The code uses the <xref:System.Configuration.ConfigurationManager.OpenExeConfiguration%2A> method to open the **app.config** file for editing, and the <xref:System.Configuration.ConfigurationManager.GetSection%2A> method returns the **connectionStrings** section. The code then checks the <xref:System.Configuration.SectionInformation.IsProtected%2A> property, calling the <xref:System.Configuration.SectionInformation.ProtectSection%2A> to encrypt the section if it is not encrypted. The <xref:System.Configuration.SectionInformation.UnprotectSection%2A> method is invoked to decrypt the section. The <xref:System.Configuration.Configuration.Save%2A> method completes the operation and saves the changes.
|
||||
|
||||
> The <xref:System.Security.Cryptography> namespace contains classes that provide additional options for encrypting and decrypting data. Use these classes if you require cryptographic services that are not available using protected configuration. Some of these classes are wrappers for the unmanaged Microsoft CryptoAPI, while others are purely managed implementations. For more information, see [Cryptographic Services](/previous-versions/visualstudio/visual-studio-2008/93bskf9z(v=vs.90)).
|
||||
|
||||
### App.config Example
|
||||
|
||||
This example demonstrates how to toggle encrypting the **connectionStrings** section in an **app.config** file for a Windows application. In this example, the procedure takes the name of the application as an argument, for example, "MyApplication.exe". The **app.config** file is then encrypted and copied to the folder that contains the executable under the name of "MyApplication.exe.config".
|
||||
|
||||
> [!NOTE]
|
||||
> You must set a reference to `System.Configuration.dll` in your project for the code to run.
|
||||
|
||||
> The connection string can only be decrypted on the computer on which it was encrypted.
|
||||
|
||||
The code uses the <xref:System.Configuration.ConfigurationManager.OpenExeConfiguration%2A> method to open the **app.config** file for editing, and the <xref:System.Configuration.ConfigurationManager.GetSection%2A> method returns the **connectionStrings** section. The code then checks the <xref:System.Configuration.SectionInformation.IsProtected%2A> property, calling the <xref:System.Configuration.SectionInformation.ProtectSection%2A> to encrypt the section if it is not encrypted. The <xref:System.Configuration.SectionInformation.UnprotectSection%2A> method is invoked to decrypt the section. The <xref:System.Configuration.Configuration.Save%2A> method completes the operation and saves the changes.
|
||||
|
||||
> [!NOTE]
|
||||
> You must add a reference to `System.Configuration.dll` in your project for the code to run.
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStrings.Encrypt#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStrings.Encrypt/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStrings.Encrypt#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStrings.Encrypt/VB/source.vb#1)]
|
||||
|
||||
### Web.config Example
|
||||
[!code-vb[DataWorks ConnectionStrings.Encrypt#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStrings.Encrypt/VB/source.vb#1)]
|
||||
|
||||
### Web.config Example
|
||||
|
||||
This example uses the <xref:System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration%2A> method of the `WebConfigurationManager`. In this case, you can supply the relative path to the **Web.config** file by using a tilde. The code requires a reference to the `System.Web.Configuration` class.
|
||||
|
||||
This example uses the <xref:System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration%2A> method of the `WebConfigurationManager`. Note that in this case you can supply the relative path to the **Web.config** file by using a tilde. The code requires a reference to the `System.Web.Configuration` class.
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringsWeb.Encrypt#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringsWeb.Encrypt/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringsWeb.Encrypt#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringsWeb.Encrypt/VB/source.vb#1)]
|
||||
|
||||
For more information about securing ASP.NET applications, see [Securing ASP.NET web sites](/previous-versions/aspnet/91f66yxt(v=vs.100)).
|
||||
|
||||
[!code-vb[DataWorks ConnectionStringsWeb.Encrypt#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringsWeb.Encrypt/VB/source.vb#1)]
|
||||
|
||||
For more information about securing ASP.NET applications, see [Securing ASP.NET web sites](/previous-versions/aspnet/91f66yxt(v=vs.100)).
|
||||
|
||||
## See also
|
||||
|
||||
- [Connection String Builders](connection-string-builders.md)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
title: "Connection Strings"
|
||||
description: Learn about connection strings in ADO.NET, which contain initialization information passed as a parameter from a data provider to a data source.
|
||||
ms.date: "10/10/2018"
|
||||
ms.assetid: 745c5f95-2f02-4674-b378-6d51a7ec2490
|
||||
---
|
||||
|
||||
# Connection Strings in ADO.NET
|
||||
|
@ -49,13 +48,15 @@ Keyword=a=b=c
|
|||
|
||||
Since each value is read till the next semicolon or the end of string, the value in the latter example is `a=b=c`, and the final semicolon is optional.
|
||||
|
||||
All connection strings share the same basic syntax described above. The set of recognized keywords depends on the provider, however, and has evolved over the years from earlier APIs such as *ODBC*. The *.NET Framework* data provider for *SQL Server* (`SqlClient`) supports many keywords from older APIs, but is generally more flexible and accepts synonyms for many of the common connection string keywords.
|
||||
All connection strings share the same basic syntax described previously. The set of recognized keywords depends on the provider, however, and has evolved over the years from earlier APIs such as *ODBC*. The *.NET Framework* data provider for *SQL Server* (`SqlClient`) supports many keywords from older APIs, but is generally more flexible and accepts synonyms for many of the common connection string keywords.
|
||||
|
||||
Typing mistakes can cause errors. For example, `Integrated Security=true` is valid, but `IntegratedSecurity=true` causes an error.
|
||||
|
||||
Connection strings constructed manually at run time from unvalidated user input are vulnerable to string-injection attacks and jeopardize security at the data source. To address these problems, *ADO.NET* 2.0 introduced [connection string builders](connection-string-builders.md) for each *.NET Framework* data provider. These connection string builders expose parameters as strongly typed properties, and make it possible to validate the connection string before it's sent to the data source.
|
||||
Connection strings constructed manually at run time from unvalidated user input are vulnerable to string-injection attacks and jeopardize security at the data source. To address these problems, *ADO.NET* 2.0 introduced [connection string builders](connection-string-builders.md) for each *.NET Framework* data provider. These connection string builders expose parameters as strongly typed properties and make it possible to validate the connection string before it's sent to the data source.
|
||||
|
||||
## In This Section
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## In this section
|
||||
|
||||
[Connection String Builders](connection-string-builders.md)\
|
||||
Demonstrates how to use the `ConnectionStringBuilder` classes to construct valid connection strings at run time.
|
||||
|
|
|
@ -2,164 +2,162 @@
|
|||
title: ".NET Framework Data Providers"
|
||||
description: Learn how a .NET Framework data provider is used to connect to a database, run commands, and retrieve results in ADO.NET.
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 03a9fc62-2d24-491a-9fe6-d6bdb6dcb131
|
||||
---
|
||||
# .NET Framework Data Providers
|
||||
# .NET Framework data providers
|
||||
|
||||
A .NET Framework data provider is used for connecting to a database, executing commands, and retrieving results. Those results are either processed directly, placed in a <xref:System.Data.DataSet> in order to be exposed to the user as needed, combined with data from multiple sources, or remoted between tiers. .NET Framework data providers are lightweight, creating a minimal layer between the data source and code, increasing performance without sacrificing functionality.
|
||||
|
||||
The following table lists the data providers that are included in the .NET Framework.
|
||||
|
||||
|.NET Framework data provider|Description|
|
||||
|-------------------------------------------------------------------------------|-----------------|
|
||||
|.NET Framework Data Provider for SQL Server|Provides data access for Microsoft SQL Server. Uses the <xref:System.Data.SqlClient> namespace.|
|
||||
|.NET Framework Data Provider for OLE DB|For data sources exposed by using OLE DB. Uses the <xref:System.Data.OleDb> namespace.|
|
||||
|.NET Framework Data Provider for ODBC|For data sources exposed by using ODBC. Uses the <xref:System.Data.Odbc> namespace.|
|
||||
|.NET Framework Data Provider for Oracle|For Oracle data sources. The .NET Framework Data Provider for Oracle supports Oracle client software version 8.1.7 and later, and uses the <xref:System.Data.OracleClient> namespace.|
|
||||
|EntityClient Provider|Provides data access for Entity Data Model (EDM) applications. Uses the <xref:System.Data.EntityClient> namespace.|
|
||||
|.NET Framework Data Provider for SQL Server Compact 4.0.|Provides data access for Microsoft SQL Server Compact 4.0. Uses the [System.Data.SqlServerCe](/previous-versions/sql/compact/sql-server-compact-4.0/ec4st0e3(v=vs.100)) namespace.|
|
||||
|
||||
## Core Objects of .NET Framework Data Providers
|
||||
A .NET Framework data provider is used for connecting to a database, executing commands, and retrieving results. Those results are either processed directly, placed in a <xref:System.Data.DataSet> in order to be exposed to the user as needed, combined with data from multiple sources, or remoted between tiers. .NET Framework data providers are lightweight, creating a minimal layer between the data source and code, increasing performance without sacrificing functionality.
|
||||
|
||||
The following table outlines the four core objects that make up a .NET Framework data provider.
|
||||
|
||||
|Object|Description|
|
||||
|------------|-----------------|
|
||||
|`Connection`|Establishes a connection to a specific data source. The base class for all `Connection` objects is the <xref:System.Data.Common.DbConnection> class.|
|
||||
|`Command`|Executes a command against a data source. Exposes `Parameters` and can execute in the scope of a `Transaction` from a `Connection`. The base class for all `Command` objects is the <xref:System.Data.Common.DbCommand> class.|
|
||||
|`DataReader`|Reads a forward-only, read-only stream of data from a data source. The base class for all `DataReader` objects is the <xref:System.Data.Common.DbDataReader> class.|
|
||||
|`DataAdapter`|Populates a `DataSet` and resolves updates with the data source. The base class for all `DataAdapter` objects is the <xref:System.Data.Common.DbDataAdapter> class.|
|
||||
|
||||
In addition to the core classes listed in the table earlier in this document, a .NET Framework data provider also contains the classes listed in the following table.
|
||||
|
||||
|Object|Description|
|
||||
|------------|-----------------|
|
||||
|`Transaction`|Enlists commands in transactions at the data source. The base class for all `Transaction` objects is the <xref:System.Data.Common.DbTransaction> class. ADO.NET also provides support for transactions using classes in the <xref:System.Transactions> namespace.|
|
||||
|`CommandBuilder`|A helper object that automatically generates command properties of a `DataAdapter` or derives parameter information from a stored procedure and populates the `Parameters` collection of a `Command` object. The base class for all `CommandBuilder` objects is the <xref:System.Data.Common.DbCommandBuilder> class.|
|
||||
|`ConnectionStringBuilder`|A helper object that provides a simple way to create and manage the contents of connection strings used by the `Connection` objects. The base class for all `ConnectionStringBuilder` objects is the <xref:System.Data.Common.DbConnectionStringBuilder> class.|
|
||||
|`Parameter`|Defines input, output, and return value parameters for commands and stored procedures. The base class for all `Parameter` objects is the <xref:System.Data.Common.DbParameter> class.|
|
||||
|`Exception`|Returned when an error is encountered at the data source. For an error encountered at the client, .NET Framework data providers throw a .NET Framework exception. The base class for all `Exception` objects is the <xref:System.Data.Common.DbException> class.|
|
||||
|`Error`|Exposes the information from a warning or error returned by a data source.|
|
||||
|`ClientPermission`|Provided for .NET Framework data provider code access security attributes. The base class for all `ClientPermission` objects is the <xref:System.Data.Common.DBDataPermission> class.|
|
||||
|
||||
## .NET Framework Data Provider for SQL Server (SqlClient)
|
||||
The following table lists the data providers that are included in .NET Framework.
|
||||
|
||||
| .NET Framework data provider | Description |
|
||||
|------------------------------|-------------|
|
||||
|.NET Framework Data Provider for SQL Server|Provides data access for Microsoft SQL Server. Uses the <xref:System.Data.SqlClient> namespace.|
|
||||
|.NET Framework Data Provider for OLE DB|For data sources exposed by using OLE DB. Uses the <xref:System.Data.OleDb> namespace.|
|
||||
|.NET Framework Data Provider for ODBC|For data sources exposed by using ODBC. Uses the <xref:System.Data.Odbc> namespace.|
|
||||
|.NET Framework Data Provider for Oracle|For Oracle data sources. The .NET Framework Data Provider for Oracle supports Oracle client software version 8.1.7 and later, and uses the <xref:System.Data.OracleClient> namespace.|
|
||||
|EntityClient Provider|Provides data access for Entity Data Model (EDM) applications. Uses the <xref:System.Data.EntityClient> namespace.|
|
||||
|.NET Framework Data Provider for SQL Server Compact 4.0.|Provides data access for Microsoft SQL Server Compact 4.0. Uses the [System.Data.SqlServerCe](/previous-versions/sql/compact/sql-server-compact-4.0/ec4st0e3(v=vs.100)) namespace.|
|
||||
|
||||
## Core Objects of .NET Framework Data Providers
|
||||
|
||||
The following table outlines the four core objects that make up a .NET Framework data provider.
|
||||
|
||||
|Object|Description|
|
||||
|------------|-----------------|
|
||||
|`Connection`|Establishes a connection to a specific data source. The base class for all `Connection` objects is the <xref:System.Data.Common.DbConnection> class.|
|
||||
|`Command`|Executes a command against a data source. Exposes `Parameters` and can execute in the scope of a `Transaction` from a `Connection`. The base class for all `Command` objects is the <xref:System.Data.Common.DbCommand> class.|
|
||||
|`DataReader`|Reads a forward-only, read-only stream of data from a data source. The base class for all `DataReader` objects is the <xref:System.Data.Common.DbDataReader> class.|
|
||||
|`DataAdapter`|Populates a `DataSet` and resolves updates with the data source. The base class for all `DataAdapter` objects is the <xref:System.Data.Common.DbDataAdapter> class.|
|
||||
|
||||
In addition to the core classes listed in the table earlier in this document, a .NET Framework data provider also contains the classes listed in the following table.
|
||||
|
||||
|Object|Description|
|
||||
|------------|-----------------|
|
||||
|`Transaction`|Enlists commands in transactions at the data source. The base class for all `Transaction` objects is the <xref:System.Data.Common.DbTransaction> class. ADO.NET also provides support for transactions using classes in the <xref:System.Transactions> namespace.|
|
||||
|`CommandBuilder`|A helper object that automatically generates command properties of a `DataAdapter` or derives parameter information from a stored procedure and populates the `Parameters` collection of a `Command` object. The base class for all `CommandBuilder` objects is the <xref:System.Data.Common.DbCommandBuilder> class.|
|
||||
|`ConnectionStringBuilder`|A helper object that provides a simple way to create and manage the contents of connection strings used by the `Connection` objects. The base class for all `ConnectionStringBuilder` objects is the <xref:System.Data.Common.DbConnectionStringBuilder> class.|
|
||||
|`Parameter`|Defines input, output, and return value parameters for commands and stored procedures. The base class for all `Parameter` objects is the <xref:System.Data.Common.DbParameter> class.|
|
||||
|`Exception`|Returned when an error is encountered at the data source. For an error encountered at the client, .NET Framework data providers throw a .NET Framework exception. The base class for all `Exception` objects is the <xref:System.Data.Common.DbException> class.|
|
||||
|`Error`|Exposes the information from a warning or error returned by a data source.|
|
||||
|`ClientPermission`|Provided for .NET Framework data provider code access security attributes. The base class for all `ClientPermission` objects is the <xref:System.Data.Common.DBDataPermission> class.|
|
||||
|
||||
## .NET Framework Data Provider for SQL Server (SqlClient)
|
||||
|
||||
The .NET Framework Data Provider for SQL Server (SqlClient) uses its own protocol to communicate with SQL Server. It is lightweight and performs well because it is optimized to access a SQL Server directly without adding an OLE DB or Open Database Connectivity (ODBC) layer. The following illustration contrasts the .NET Framework Data Provider for SQL Server with the .NET Framework Data Provider for OLE DB. The .NET Framework Data Provider for OLE DB communicates to an OLE DB data source through both the OLE DB Service component, which provides connection pooling and transaction services, and the OLE DB provider for the data source.
|
||||
|
||||
The .NET Framework Data Provider for SQL Server (SqlClient) uses its own protocol to communicate with SQL Server. It is lightweight and performs well because it is optimized to access a SQL Server directly without adding an OLE DB or Open Database Connectivity (ODBC) layer. The following illustration contrasts the .NET Framework Data Provider for SQL Server with the .NET Framework Data Provider for OLE DB. The .NET Framework Data Provider for OLE DB communicates to an OLE DB data source through both the OLE DB Service component, which provides connection pooling and transaction services, and the OLE DB provider for the data source.
|
||||
|
||||
> [!NOTE]
|
||||
> The .NET Framework Data Provider for ODBC has a similar architecture to the .NET Framework Data Provider for OLE DB; for example, it calls into an ODBC Service Component.
|
||||
|
||||
![Data providers](./media/netdataproviders-bpuedev11.gif "NETDataProviders_bpuedev11")
|
||||
Comparison of the .NET Framework Data Provider for SQL Server and the .NET Framework Data Provider for OLE DB
|
||||
|
||||
The .NET Framework Data Provider for SQL Server classes are located in the <xref:System.Data.SqlClient> namespace.
|
||||
|
||||
The .NET Framework Data Provider for SQL Server supports both local and distributed transactions. For distributed transactions, the .NET Framework Data Provider for SQL Server, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services or <xref:System.Transactions>. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following code example shows how to include the `System.Data.SqlClient` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.SqlClient;
|
||||
```
|
||||
|
||||
## .NET Framework Data Provider for OLE DB
|
||||
> The .NET Framework Data Provider for ODBC has a similar architecture to the .NET Framework Data Provider for OLE DB; for example, it calls into an ODBC Service Component.
|
||||
|
||||
![Comparison of .NET Framework Data Provider for SQL Server and .NET Framework Data Provider for OLE DB.](./media/netdataproviders-bpuedev11.gif)
|
||||
|
||||
The .NET Framework Data Provider for SQL Server classes are located in the <xref:System.Data.SqlClient> namespace.
|
||||
|
||||
The .NET Framework Data Provider for SQL Server supports both local and distributed transactions. For distributed transactions, the .NET Framework Data Provider for SQL Server, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services or <xref:System.Transactions>. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following code example shows how to include the `System.Data.SqlClient` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.SqlClient;
|
||||
```
|
||||
|
||||
## .NET Framework Data Provider for OLE DB
|
||||
|
||||
The .NET Framework Data Provider for OLE DB (OleDb) uses native OLE DB through COM interop to enable data access. The .NET Framework Data Provider for OLE DB supports both local and distributed transactions. For distributed transactions, the .NET Framework Data Provider for OLE DB, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following table shows the providers that have been tested with ADO.NET.
|
||||
|
||||
| Driver | Provider |
|
||||
|-------------------------|------------------------------------------|
|
||||
| SQLOLEDB | Microsoft OLE DB provider for SQL Server |
|
||||
| MSDAORA | Microsoft OLE DB provider for Oracle |
|
||||
| Microsoft.Jet.OLEDB.4.0 | OLE DB provider for Microsoft Jet |
|
||||
|
||||
The .NET Framework Data Provider for OLE DB (OleDb) uses native OLE DB through COM interop to enable data access. The .NET Framework Data Provider for OLE DB supports both local and distributed transactions. For distributed transactions, the .NET Framework Data Provider for OLE DB, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following table shows the providers that have been tested with ADO.NET.
|
||||
|
||||
|Driver|Provider|
|
||||
|------------|--------------|
|
||||
|SQLOLEDB|Microsoft OLE DB provider for SQL Server|
|
||||
|MSDAORA|Microsoft OLE DB provider for Oracle|
|
||||
|Microsoft.Jet.OLEDB.4.0|OLE DB provider for Microsoft Jet|
|
||||
|
||||
> [!NOTE]
|
||||
> Using an Access (Jet) database as a data source for multithreaded applications, such as ASP.NET applications, is not recommended. If you must use Jet as a data source for an ASP.NET application, realize that ASP.NET applications connecting to an Access database can encounter connection problems.
|
||||
|
||||
The .NET Framework Data Provider for OLE DB does not support OLE DB version 2.5 interfaces. OLE DB Providers that require support for OLE DB 2.5 interfaces will not function correctly with the .NET Framework Data Provider for OLE DB. This includes the Microsoft OLE DB provider for Exchange and the Microsoft OLE DB provider for Internet Publishing.
|
||||
|
||||
The .NET Framework Data Provider for OLE DB does not work with the OLE DB provider for ODBC (MSDASQL). To access an ODBC data source using ADO.NET, use the .NET Framework Data Provider for ODBC.
|
||||
|
||||
.NET Framework Data Provider for OLE DB classes are located in the <xref:System.Data.OleDb> namespace. The following code example shows how to include the `System.Data.OleDb` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.OleDb
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.OleDb;
|
||||
```
|
||||
|
||||
## .NET Framework Data Provider for ODBC
|
||||
> Using an Access (Jet) database as a data source for multithreaded applications, such as ASP.NET applications, is not recommended. If you must use Jet as a data source for an ASP.NET application, realize that ASP.NET applications connecting to an Access database can encounter connection problems.
|
||||
|
||||
The .NET Framework Data Provider for OLE DB does not support OLE DB version 2.5 interfaces. OLE DB Providers that require support for OLE DB 2.5 interfaces will not function correctly with the .NET Framework Data Provider for OLE DB. This includes the Microsoft OLE DB provider for Exchange and the Microsoft OLE DB provider for Internet Publishing.
|
||||
|
||||
The .NET Framework Data Provider for OLE DB does not work with the OLE DB provider for ODBC (MSDASQL). To access an ODBC data source using ADO.NET, use the .NET Framework Data Provider for ODBC.
|
||||
|
||||
.NET Framework Data Provider for OLE DB classes are located in the <xref:System.Data.OleDb> namespace. The following code example shows how to include the `System.Data.OleDb` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.OleDb
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.OleDb;
|
||||
```
|
||||
|
||||
## .NET Framework Data Provider for ODBC
|
||||
|
||||
The .NET Framework Data Provider for ODBC (Odbc) uses the native ODBC Driver Manager (DM) to enable data access. The ODBC data provider supports both local and distributed transactions. For distributed transactions, the ODBC data provider, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following table shows the ODBC drivers tested with ADO.NET.
|
||||
|
||||
| Driver |
|
||||
|---------------------------------|
|
||||
| SQL Server |
|
||||
| Microsoft ODBC for Oracle |
|
||||
| Microsoft Access Driver (*.mdb) |
|
||||
|
||||
.NET Framework Data Provider for ODBC classes are located in the <xref:System.Data.Odbc> namespace.
|
||||
|
||||
The following code example shows how to include the `System.Data.Odbc` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.Odbc
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.Odbc;
|
||||
```
|
||||
|
||||
The .NET Framework Data Provider for ODBC (Odbc) uses the native ODBC Driver Manager (DM) to enable data access. The ODBC data provider supports both local and distributed transactions. For distributed transactions, the ODBC data provider, by default, automatically enlists in a transaction and obtains transaction details from Windows Component Services. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The following table shows the ODBC drivers tested with ADO.NET.
|
||||
|
||||
|Driver|
|
||||
|------------|
|
||||
|SQL Server|
|
||||
|Microsoft ODBC for Oracle|
|
||||
|Microsoft Access Driver (*.mdb)|
|
||||
|
||||
.NET Framework Data Provider for ODBC classes are located in the <xref:System.Data.Odbc> namespace.
|
||||
|
||||
The following code example shows how to include the `System.Data.Odbc` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data.Odbc
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data.Odbc;
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The .NET Framework Data Provider for ODBC requires MDAC 2.6 or a later version, and MDAC 2.8 SP1 is recommended.
|
||||
|
||||
## .NET Framework Data Provider for Oracle
|
||||
|
||||
The .NET Framework Data Provider for Oracle (OracleClient) enables data access to Oracle data sources through Oracle client connectivity software. The data provider supports Oracle client software version 8.1.7 or a later version. The data provider supports both local and distributed transactions. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The .NET Framework Data Provider for Oracle requires Oracle client software (version 8.1.7 or a later version) on the system before you can connect to an Oracle data source.
|
||||
|
||||
.NET Framework Data Provider for Oracle classes are located in the <xref:System.Data.OracleClient> namespace and are contained in the `System.Data.OracleClient.dll` assembly. You must reference both the `System.Data.dll` and the `System.Data.OracleClient.dll` when you compile an application that uses the data provider.
|
||||
|
||||
The following code example shows how to include the `System.Data.OracleClient` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data
|
||||
Imports System.Data.OracleClient
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data;
|
||||
using System.Data.OracleClient;
|
||||
```
|
||||
|
||||
## Choosing a .NET Framework Data Provider
|
||||
## .NET Framework Data Provider for Oracle
|
||||
|
||||
Depending on the design and data source for your application, your choice of .NET Framework data provider can improve the performance, capability, and integrity of your application. The following table discusses the advantages and limitations of each .NET Framework data provider.
|
||||
|
||||
|Provider|Notes|
|
||||
|--------------|-----------|
|
||||
|.NET Framework Data Provider for SQL Server|Recommended for middle-tier applications that use Microsoft SQL Server.<br /><br /> Recommended for single-tier applications that use Microsoft Database Engine (MSDE) or SQL Server.<br /><br /> Recommended over use of the OLE DB provider for SQL Server (SQLOLEDB) with the .NET Framework Data Provider for OLE DB.|
|
||||
|.NET Framework Data Provider for OLE DB|For SQL Server, the .NET Framework Data Provider for SQL Server is recommended instead of this provider.<br /><br /> Recommended for single-tier applications that use Microsoft Access databases. Use of an Access database for a middle-tier application is not recommended.|
|
||||
|.NET Framework Data Provider for ODBC|Recommended for middle and single-tier applications that use ODBC data sources.|
|
||||
|.NET Framework Data Provider for Oracle|Recommended for middle and single-tier applications that use Oracle data sources.|
|
||||
|
||||
## EntityClient Provider
|
||||
The .NET Framework Data Provider for Oracle (OracleClient) enables data access to Oracle data sources through Oracle client connectivity software. The data provider supports Oracle client software version 8.1.7 or a later version. The data provider supports both local and distributed transactions. For more information, see [Transactions and Concurrency](transactions-and-concurrency.md).
|
||||
|
||||
The .NET Framework Data Provider for Oracle requires Oracle client software (version 8.1.7 or a later version) on the system before you can connect to an Oracle data source.
|
||||
|
||||
.NET Framework Data Provider for Oracle classes are located in the <xref:System.Data.OracleClient> namespace and are contained in the `System.Data.OracleClient.dll` assembly. You must reference both the `System.Data.dll` and the `System.Data.OracleClient.dll` when you compile an application that uses the data provider.
|
||||
|
||||
The following code example shows how to include the `System.Data.OracleClient` namespace in your applications.
|
||||
|
||||
```vb
|
||||
Imports System.Data
|
||||
Imports System.Data.OracleClient
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System.Data;
|
||||
using System.Data.OracleClient;
|
||||
```
|
||||
|
||||
## Choose a .NET Framework Data Provider
|
||||
|
||||
Depending on the design and data source for your application, your choice of .NET Framework data provider can improve the performance, capability, and integrity of your application. The following table discusses the advantages and limitations of each .NET Framework data provider.
|
||||
|
||||
|Provider|Notes|
|
||||
|--------------|-----------|
|
||||
|.NET Framework Data Provider for SQL Server|Recommended for middle-tier applications that use Microsoft SQL Server.<br /><br /> Recommended for single-tier applications that use Microsoft Database Engine (MSDE) or SQL Server.<br /><br /> Recommended over use of the OLE DB provider for SQL Server (SQLOLEDB) with the .NET Framework Data Provider for OLE DB.|
|
||||
|.NET Framework Data Provider for OLE DB|For SQL Server, the .NET Framework Data Provider for SQL Server is recommended instead of this provider.<br /><br /> Recommended for single-tier applications that use Microsoft Access databases. Use of an Access database for a middle-tier application is not recommended.|
|
||||
|.NET Framework Data Provider for ODBC|Recommended for middle and single-tier applications that use ODBC data sources.|
|
||||
|.NET Framework Data Provider for Oracle|Recommended for middle and single-tier applications that use Oracle data sources.|
|
||||
|
||||
## EntityClient Provider
|
||||
|
||||
The EntityClient provider is used for accessing data based on an Entity Data Model (EDM). Unlike the other .NET Framework data providers, it does not interact directly with a data source. Instead, it uses Entity SQL to communicate with the underlying data provider. For more information, see [EntityClient Provider for the Entity Framework](./ef/entityclient-provider-for-the-entity-framework.md).
|
||||
|
||||
The EntityClient provider is used for accessing data based on an Entity Data Model (EDM). Unlike the other .NET Framework data providers, it does not interact directly with a data source. Instead, it uses Entity SQL to communicate with the underlying data provider. For more information, see [EntityClient Provider for the Entity Framework](./ef/entityclient-provider-for-the-entity-framework.md).
|
||||
|
||||
## See also
|
||||
|
||||
- [ADO.NET Overview](ado-net-overview.md)
|
||||
|
|
|
@ -1,207 +1,203 @@
|
|||
---
|
||||
description: "Learn more about: Creating a DataTable from a DataView"
|
||||
description: "Learn more about creating a DataTable from a DataView by calling DataView.ToTable to copy all or some of the data."
|
||||
title: "Creating a DataTable from a DataView"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 2d45cf41-d8ae-4409-af3e-a96a7e476d85
|
||||
---
|
||||
# Creating a DataTable from a DataView
|
||||
# Create a DataTable from a DataView
|
||||
|
||||
Once you have retrieved data from a data source, and have filled a <xref:System.Data.DataTable> with the data, you may want to sort, filter, or otherwise limit the returned data without retrieving it again. The <xref:System.Data.DataView> class makes this possible. In addition, if you need to create a new <xref:System.Data.DataTable> from the <xref:System.Data.DataView>, you can use the <xref:System.Data.DataView.ToTable%2A> method to copy all the rows and columns, or a subset of the data into a new <xref:System.Data.DataTable>. The <xref:System.Data.DataView.ToTable%2A> method provides overloads to:
|
||||
|
||||
- Create a <xref:System.Data.DataTable> containing columns that are a subset of the columns in the <xref:System.Data.DataView>.
|
||||
|
||||
- Create a <xref:System.Data.DataTable> that includes only distinct rows from the <xref:System.Data.DataView>, analogously to the DISTINCT keyword in Transact-SQL.
|
||||
|
||||
## Example
|
||||
Once you've retrieved data from a data source,and have filled a <xref:System.Data.DataTable> with the data, you might want to sort, filter, or otherwise limit the returned data without retrieving it again. The <xref:System.Data.DataView> class makes this possible. In addition, if you need to create a new <xref:System.Data.DataTable> from the <xref:System.Data.DataView>, you can use the <xref:System.Data.DataView.ToTable%2A> method to copy all the rows and columns, or a subset of the data, into a new <xref:System.Data.DataTable>. The <xref:System.Data.DataView.ToTable%2A> method provides overloads to:
|
||||
|
||||
The following console application example creates a <xref:System.Data.DataTable> that contains data from the **Person.Contact** table in the **AdventureWorks** sample database. Next, the example creates a sorted and filtered <xref:System.Data.DataView> based on the <xref:System.Data.DataTable>. After displaying the contents of the <xref:System.Data.DataTable> and the <xref:System.Data.DataView>, the example creates a new <xref:System.Data.DataTable> from the <xref:System.Data.DataView> by calling the <xref:System.Data.DataView.ToTable%2A> method, selecting only a subset of the available columns. Finally, the example displays the contents of the new <xref:System.Data.DataTable>.
|
||||
|
||||
```vb
|
||||
Private Sub DemonstrateDataView()
|
||||
' Retrieve a DataTable from the AdventureWorks sample database.
|
||||
' connectionString is assumed to be a valid connection string.
|
||||
Dim adapter As New SqlDataAdapter( _
|
||||
"SELECT FirstName, LastName, EmailAddress FROM Person.Contact WHERE FirstName LIKE 'Mich%'", connectionString)
|
||||
Dim table As New DataTable
|
||||
|
||||
adapter.Fill(table)
|
||||
Console.WriteLine("Original table name: " & table.TableName)
|
||||
' Print current table values.
|
||||
PrintTableOrView(table, "Current Values in Table")
|
||||
|
||||
' Now create a DataView based on the DataTable.
|
||||
' Sort and filter the data.
|
||||
Dim view As DataView = table.DefaultView
|
||||
view.Sort = "LastName, FirstName"
|
||||
view.RowFilter = "LastName > 'M'"
|
||||
PrintTableOrView(view, "Current Values in View")
|
||||
|
||||
' Create a new DataTable based on the DataView,
|
||||
' requesting only two columns with distinct values
|
||||
' in the columns.
|
||||
Dim newTable As DataTable = view.ToTable("UniqueLastNames", True, "FirstName", "LastName")
|
||||
PrintTableOrView(newTable, "Table created from DataView")
|
||||
Console.WriteLine("New table name: " & newTable.TableName)
|
||||
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Sub
|
||||
|
||||
Private Sub PrintTableOrView(ByVal dv As DataView, ByVal label As String)
|
||||
Dim sw As System.IO.StringWriter
|
||||
Dim output As String
|
||||
Dim table As DataTable = dv.Table
|
||||
|
||||
Console.WriteLine(label)
|
||||
|
||||
' Loop through each row in the view.
|
||||
For Each rowView As DataRowView In dv
|
||||
sw = New System.IO.StringWriter
|
||||
|
||||
' Loop through each column.
|
||||
For Each col As DataColumn In table.Columns
|
||||
' Output the value of each column's data.
|
||||
sw.Write(rowView(col.ColumnName).ToString() & ", ")
|
||||
Next
|
||||
output = sw.ToString
|
||||
' Trim off the trailing ", ", so the output looks correct.
|
||||
If output.Length > 2 Then
|
||||
output = output.Substring(0, output.Length - 2)
|
||||
End If
|
||||
' Display the row in the console window.
|
||||
Console.WriteLine(output)
|
||||
Next
|
||||
Console.WriteLine()
|
||||
End Sub
|
||||
|
||||
Private Sub PrintTableOrView(ByVal table As DataTable, ByVal label As String)
|
||||
Dim sw As System.IO.StringWriter
|
||||
Dim output As String
|
||||
|
||||
Console.WriteLine(label)
|
||||
|
||||
' Loop through each row in the table.
|
||||
For Each row As DataRow In table.Rows
|
||||
sw = New System.IO.StringWriter
|
||||
' Loop through each column.
|
||||
For Each col As DataColumn In table.Columns
|
||||
' Output the value of each column's data.
|
||||
sw.Write(row(col).ToString() & ", ")
|
||||
Next
|
||||
output = sw.ToString
|
||||
' Trim off the trailing ", ", so the output looks correct.
|
||||
If output.Length > 2 Then
|
||||
output = output.Substring(0, output.Length - 2)
|
||||
End If
|
||||
' Display the row in the console window.
|
||||
Console.WriteLine(output)
|
||||
Next
|
||||
Console.WriteLine()
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
private static void DemonstrateDataView()
|
||||
{
|
||||
// Retrieve a DataTable from the AdventureWorks sample database.
|
||||
// connectionString is assumed to be a valid connection string.
|
||||
SqlDataAdapter adapter = new SqlDataAdapter(
|
||||
"SELECT FirstName, LastName, EmailAddress " +
|
||||
- Create a <xref:System.Data.DataTable> containing columns that are a subset of the columns in the <xref:System.Data.DataView>.
|
||||
- Create a <xref:System.Data.DataTable> that includes only distinct rows from the <xref:System.Data.DataView>, analogously to the `DISTINCT` keyword in Transact-SQL.
|
||||
|
||||
## Example
|
||||
|
||||
The following console application example creates a <xref:System.Data.DataTable> that contains data from the **Person.Contact** table in the **AdventureWorks** sample database. Next, the example creates a sorted and filtered <xref:System.Data.DataView> based on the <xref:System.Data.DataTable>. After displaying the contents of the <xref:System.Data.DataTable> and the <xref:System.Data.DataView>, the example creates a new <xref:System.Data.DataTable> from the <xref:System.Data.DataView> by calling the <xref:System.Data.DataView.ToTable%2A> method, selecting only a subset of the available columns. Finally, the example displays the contents of the new <xref:System.Data.DataTable>.
|
||||
|
||||
```vb
|
||||
Private Sub DemonstrateDataView()
|
||||
' Retrieve a DataTable from the AdventureWorks sample database.
|
||||
' connectionString is assumed to be a valid connection string.
|
||||
Dim adapter As New SqlDataAdapter( _
|
||||
"SELECT FirstName, LastName, EmailAddress FROM Person.Contact WHERE FirstName LIKE 'Mich%'", connectionString)
|
||||
Dim table As New DataTable
|
||||
|
||||
adapter.Fill(table)
|
||||
Console.WriteLine("Original table name: " & table.TableName)
|
||||
' Print current table values.
|
||||
PrintTableOrView(table, "Current Values in Table")
|
||||
|
||||
' Now create a DataView based on the DataTable.
|
||||
' Sort and filter the data.
|
||||
Dim view As DataView = table.DefaultView
|
||||
view.Sort = "LastName, FirstName"
|
||||
view.RowFilter = "LastName > 'M'"
|
||||
PrintTableOrView(view, "Current Values in View")
|
||||
|
||||
' Create a new DataTable based on the DataView,
|
||||
' requesting only two columns with distinct values
|
||||
' in the columns.
|
||||
Dim newTable As DataTable = view.ToTable("UniqueLastNames", True, "FirstName", "LastName")
|
||||
PrintTableOrView(newTable, "Table created from DataView")
|
||||
Console.WriteLine("New table name: " & newTable.TableName)
|
||||
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Sub
|
||||
|
||||
Private Sub PrintTableOrView(ByVal dv As DataView, ByVal label As String)
|
||||
Dim sw As System.IO.StringWriter
|
||||
Dim output As String
|
||||
Dim table As DataTable = dv.Table
|
||||
|
||||
Console.WriteLine(label)
|
||||
|
||||
' Loop through each row in the view.
|
||||
For Each rowView As DataRowView In dv
|
||||
sw = New System.IO.StringWriter
|
||||
|
||||
' Loop through each column.
|
||||
For Each col As DataColumn In table.Columns
|
||||
' Output the value of each column's data.
|
||||
sw.Write(rowView(col.ColumnName).ToString() & ", ")
|
||||
Next
|
||||
output = sw.ToString
|
||||
' Trim off the trailing ", ", so the output looks correct.
|
||||
If output.Length > 2 Then
|
||||
output = output.Substring(0, output.Length - 2)
|
||||
End If
|
||||
' Display the row in the console window.
|
||||
Console.WriteLine(output)
|
||||
Next
|
||||
Console.WriteLine()
|
||||
End Sub
|
||||
|
||||
Private Sub PrintTableOrView(ByVal table As DataTable, ByVal label As String)
|
||||
Dim sw As System.IO.StringWriter
|
||||
Dim output As String
|
||||
|
||||
Console.WriteLine(label)
|
||||
|
||||
' Loop through each row in the table.
|
||||
For Each row As DataRow In table.Rows
|
||||
sw = New System.IO.StringWriter
|
||||
' Loop through each column.
|
||||
For Each col As DataColumn In table.Columns
|
||||
' Output the value of each column's data.
|
||||
sw.Write(row(col).ToString() & ", ")
|
||||
Next
|
||||
output = sw.ToString
|
||||
' Trim off the trailing ", ", so the output looks correct.
|
||||
If output.Length > 2 Then
|
||||
output = output.Substring(0, output.Length - 2)
|
||||
End If
|
||||
' Display the row in the console window.
|
||||
Console.WriteLine(output)
|
||||
Next
|
||||
Console.WriteLine()
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
private static void DemonstrateDataView()
|
||||
{
|
||||
// Retrieve a DataTable from the AdventureWorks sample database.
|
||||
// connectionString is assumed to be a valid connection string.
|
||||
SqlDataAdapter adapter = new SqlDataAdapter(
|
||||
"SELECT FirstName, LastName, EmailAddress " +
|
||||
"FROM Person.Contact WHERE FirstName LIKE 'Mich%'",
|
||||
GetConnectionString());
|
||||
DataTable table = new DataTable();
|
||||
|
||||
adapter.Fill(table);
|
||||
Console.WriteLine("Original table name: " + table.TableName);
|
||||
// Print current table values.
|
||||
PrintTableOrView(table, "Current Values in Table");
|
||||
|
||||
// Now create a DataView based on the DataTable.
|
||||
// Sort and filter the data.
|
||||
DataView view = table.DefaultView;
|
||||
view.Sort = "LastName, FirstName";
|
||||
view.RowFilter = "LastName > 'M'";
|
||||
PrintTableOrView(view, "Current Values in View");
|
||||
|
||||
// Create a new DataTable based on the DataView,
|
||||
// requesting only two columns with distinct values
|
||||
// in the columns.
|
||||
DataTable newTable = view.ToTable("UniqueLastNames",
|
||||
true, "FirstName", "LastName");
|
||||
PrintTableOrView(newTable, "Table created from DataView");
|
||||
Console.WriteLine("New table name: " + newTable.TableName);
|
||||
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
private static void PrintTableOrView(DataView dv, string label)
|
||||
{
|
||||
System.IO.StringWriter sw;
|
||||
string output;
|
||||
DataTable table = dv.Table;
|
||||
|
||||
Console.WriteLine(label);
|
||||
|
||||
// Loop through each row in the view.
|
||||
foreach (DataRowView rowView in dv)
|
||||
{
|
||||
sw = new System.IO.StringWriter();
|
||||
|
||||
// Loop through each column.
|
||||
foreach (DataColumn col in table.Columns)
|
||||
{
|
||||
// Output the value of each column's data.
|
||||
sw.Write(rowView[col.ColumnName].ToString() + ", ");
|
||||
}
|
||||
output = sw.ToString();
|
||||
// Trim off the trailing ", ", so the output looks correct.
|
||||
if (output.Length > 2)
|
||||
{
|
||||
output = output.Substring(0, output.Length - 2);
|
||||
}
|
||||
// Display the row in the console window.
|
||||
Console.WriteLine(output);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static void PrintTableOrView(DataTable table, string label)
|
||||
{
|
||||
System.IO.StringWriter sw;
|
||||
string output;
|
||||
|
||||
Console.WriteLine(label);
|
||||
|
||||
// Loop through each row in the table.
|
||||
foreach (DataRow row in table.Rows)
|
||||
{
|
||||
sw = new System.IO.StringWriter();
|
||||
// Loop through each column.
|
||||
foreach (DataColumn col in table.Columns)
|
||||
{
|
||||
// Output the value of each column's data.
|
||||
sw.Write(row[col].ToString() + ", ");
|
||||
}
|
||||
output = sw.ToString();
|
||||
// Trim off the trailing ", ", so the output looks correct.
|
||||
if (output.Length > 2)
|
||||
{
|
||||
output = output.Substring(0, output.Length - 2);
|
||||
}
|
||||
// Display the row in the console window.
|
||||
Console.WriteLine(output);
|
||||
} //
|
||||
Console.WriteLine();
|
||||
}
|
||||
```
|
||||
|
||||
}
|
||||
|
||||
GetConnectionString());
|
||||
DataTable table = new DataTable();
|
||||
|
||||
adapter.Fill(table);
|
||||
Console.WriteLine("Original table name: " + table.TableName);
|
||||
// Print current table values.
|
||||
PrintTableOrView(table, "Current Values in Table");
|
||||
|
||||
// Now create a DataView based on the DataTable.
|
||||
// Sort and filter the data.
|
||||
DataView view = table.DefaultView;
|
||||
view.Sort = "LastName, FirstName";
|
||||
view.RowFilter = "LastName > 'M'";
|
||||
PrintTableOrView(view, "Current Values in View");
|
||||
|
||||
// Create a new DataTable based on the DataView,
|
||||
// requesting only two columns with distinct values
|
||||
// in the columns.
|
||||
DataTable newTable = view.ToTable("UniqueLastNames",
|
||||
true, "FirstName", "LastName");
|
||||
PrintTableOrView(newTable, "Table created from DataView");
|
||||
Console.WriteLine("New table name: " + newTable.TableName);
|
||||
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
|
||||
private static void PrintTableOrView(DataView dv, string label)
|
||||
{
|
||||
System.IO.StringWriter sw;
|
||||
string output;
|
||||
DataTable table = dv.Table;
|
||||
|
||||
Console.WriteLine(label);
|
||||
|
||||
// Loop through each row in the view.
|
||||
foreach (DataRowView rowView in dv)
|
||||
{
|
||||
sw = new System.IO.StringWriter();
|
||||
|
||||
// Loop through each column.
|
||||
foreach (DataColumn col in table.Columns)
|
||||
{
|
||||
// Output the value of each column's data.
|
||||
sw.Write(rowView[col.ColumnName].ToString() + ", ");
|
||||
}
|
||||
output = sw.ToString();
|
||||
// Trim off the trailing ", ", so the output looks correct.
|
||||
if (output.Length > 2)
|
||||
{
|
||||
output = output.Substring(0, output.Length - 2);
|
||||
}
|
||||
// Display the row in the console window.
|
||||
Console.WriteLine(output);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
private static void PrintTableOrView(DataTable table, string label)
|
||||
{
|
||||
System.IO.StringWriter sw;
|
||||
string output;
|
||||
|
||||
Console.WriteLine(label);
|
||||
|
||||
// Loop through each row in the table.
|
||||
foreach (DataRow row in table.Rows)
|
||||
{
|
||||
sw = new System.IO.StringWriter();
|
||||
// Loop through each column.
|
||||
foreach (DataColumn col in table.Columns)
|
||||
{
|
||||
// Output the value of each column's data.
|
||||
sw.Write(row[col].ToString() + ", ");
|
||||
}
|
||||
output = sw.ToString();
|
||||
// Trim off the trailing ", ", so the output looks correct.
|
||||
if (output.Length > 2)
|
||||
{
|
||||
output = output.Substring(0, output.Length - 2);
|
||||
}
|
||||
// Display the row in the console window.
|
||||
Console.WriteLine(output);
|
||||
} //
|
||||
Console.WriteLine();
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- <xref:System.Data.DataView.ToTable%2A>
|
||||
|
|
|
@ -1,69 +1,68 @@
|
|||
---
|
||||
description: "Learn more about: The Load Method"
|
||||
description: "Learn more about the overloaded DataTable.Load method, which loads a DataTable with rows from a data source."
|
||||
title: "The Load Method"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "vb"
|
||||
ms.assetid: e22e5812-89c6-41f0-9302-bb899a46dbff
|
||||
---
|
||||
# The Load Method
|
||||
# The Load method
|
||||
|
||||
You can use the <xref:System.Data.DataTable.Load%2A> method to load a <xref:System.Data.DataTable> with rows from a data source. This is an overloaded method which, in its simplest form, accepts a single parameter, a **DataReader**. In this form, it simply loads the **DataTable** with rows. Optionally, you can specify the **LoadOption** parameter to control how data is added to the **DataTable**.
|
||||
|
||||
The **LoadOption** parameter is particularly useful in cases where the **DataTable** already contains rows of data, because it describes how incoming data from the data source will be combined with the data already in the table. For example, **PreserveCurrentValues** (the default) specifies that in cases where a row is marked as **Added** in the **DataTable**, the **Original** value or each column is set to the contents of the matching row from the data source. The **Current** value will retain the values assigned when the row was added, and the **RowState** of the row will be set to **Changed**.
|
||||
|
||||
The following table gives a short description of the <xref:System.Data.LoadOption> enumeration values.
|
||||
|
||||
|LoadOption value|Description|
|
||||
|----------------------|-----------------|
|
||||
|**OverwriteRow**|If incoming rows have the same **PrimaryKey** value as a row already in the **DataTable**, the **Original** and **Current** values of each column are replaced with the values in the incoming row, and the **RowState** property is set to **Unchanged**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added with a **RowState** value of **Unchanged**.<br /><br /> This option in effect refreshes the contents of the **DataTable** so that it matches the contents of the data source.|
|
||||
|**PreserveCurrentValues (default)**|If incoming rows have the same **PrimaryKey** value as a row already in the **DataTable**, the **Original** value is set to the contents of the incoming row, and the **Current** value is not changed.<br /><br /> If the **RowState** is **Added** or **Modified**, it is set to **Modified**.<br /><br /> If the **RowState** was **Deleted**, it remains **Deleted**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added, and the **RowState** is set to **Unchanged**.|
|
||||
|**UpdateCurrentValues**|If incoming rows have the same **PrimaryKey** value as the row already in the **DataTable**, the **Current** value is copied to the **Original** value, and the **Current** value is then set to the contents of the incoming row.<br /><br /> If the **RowState** in the **DataTable** was **Added**, the **RowState** remains **Added**. For rows marked as **Modified** or **Deleted**, the **RowState** is **Modified**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added, and the **RowState** is set to **Added**.|
|
||||
|
||||
The following sample uses the **Load** method to display a list of birthdays for the employees in the **Northwind** database.
|
||||
|
||||
```vb
|
||||
Private Sub LoadBirthdays(ByVal connectionString As String)
|
||||
' Assumes that connectionString is a valid connection string
|
||||
' to the Northwind database on SQL Server.
|
||||
Dim queryString As String = _
|
||||
"SELECT LastName, FirstName, BirthDate " & _
|
||||
" FROM dbo.Employees " & _
|
||||
"ORDER BY BirthDate, LastName, FirstName"
|
||||
|
||||
You can use the <xref:System.Data.DataTable.Load%2A> method to load a <xref:System.Data.DataTable> with rows from a data source. This is an overloaded method which, in its simplest form, accepts a single parameter, a **DataReader**. In this form, it simply loads the **DataTable** with rows. Optionally, you can specify the **LoadOption** parameter to control how data is added to the **DataTable**.
|
||||
|
||||
The **LoadOption** parameter is particularly useful in cases where the **DataTable** already contains rows of data, because it describes how incoming data from the data source will be combined with the data already in the table. For example, **PreserveCurrentValues** (the default) specifies that in cases where a row is marked as **Added** in the **DataTable**, the **Original** value or each column is set to the contents of the matching row from the data source. The **Current** value will retain the values assigned when the row was added, and the **RowState** of the row will be set to **Changed**.
|
||||
|
||||
The following table gives a short description of the <xref:System.Data.LoadOption> enumeration values.
|
||||
|
||||
|LoadOption value|Description|
|
||||
|----------------------|-----------------|
|
||||
|**OverwriteRow**|If incoming rows have the same **PrimaryKey** value as a row already in the **DataTable**, the **Original** and **Current** values of each column are replaced with the values in the incoming row, and the **RowState** property is set to **Unchanged**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added with a **RowState** value of **Unchanged**.<br /><br /> This option in effect refreshes the contents of the **DataTable** so that it matches the contents of the data source.|
|
||||
|**PreserveCurrentValues (default)**|If incoming rows have the same **PrimaryKey** value as a row already in the **DataTable**, the **Original** value is set to the contents of the incoming row, and the **Current** value is not changed.<br /><br /> If the **RowState** is **Added** or **Modified**, it is set to **Modified**.<br /><br /> If the **RowState** was **Deleted**, it remains **Deleted**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added, and the **RowState** is set to **Unchanged**.|
|
||||
|**UpdateCurrentValues**|If incoming rows have the same **PrimaryKey** value as the row already in the **DataTable**, the **Current** value is copied to the **Original** value, and the **Current** value is then set to the contents of the incoming row.<br /><br /> If the **RowState** in the **DataTable** was **Added**, the **RowState** remains **Added**. For rows marked as **Modified** or **Deleted**, the **RowState** is **Modified**.<br /><br /> Rows from the data source that do not already exist in the **DataTable** are added, and the **RowState** is set to **Added**.|
|
||||
|
||||
The following sample uses the **Load** method to display a list of birthdays for the employees in the **Northwind** database.
|
||||
|
||||
```vb
|
||||
Private Sub LoadBirthdays(ByVal connectionString As String)
|
||||
' Assumes that connectionString is a valid connection string
|
||||
' to the Northwind database on SQL Server.
|
||||
Dim queryString As String = _
|
||||
"SELECT LastName, FirstName, BirthDate " & _
|
||||
" FROM dbo.Employees " & _
|
||||
"ORDER BY BirthDate, LastName, FirstName"
|
||||
|
||||
' Open and fill a DataSet.
|
||||
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
|
||||
queryString, connectionString)
|
||||
Dim employees As New DataSet
|
||||
adapter.Fill(employees, "Employees")
|
||||
|
||||
' Create a SqlDataReader for use with the Load Method.
|
||||
Dim reader As DataTableReader = employees.GetDataReader()
|
||||
|
||||
' Create an instance of DataTable and assign the first
|
||||
' DataTable in the DataSet.Tables collection to it.
|
||||
Dim dataTableEmp As DataTable = employees.Tables(0)
|
||||
|
||||
' Fill the DataTable with data by calling Load and
|
||||
' passing the SqlDataReader.
|
||||
dataTableEmp.Load(reader, LoadOption.OverwriteRow)
|
||||
|
||||
' Loop through the rows collection and display the values
|
||||
' in the console window.
|
||||
Dim employeeRow As DataRow
|
||||
For Each employeeRow In dataTableEmp.Rows
|
||||
Console.WriteLine("{0:MM\\dd\\yyyy}" & ControlChars.Tab & _
|
||||
"{1}, {2}", _
|
||||
employeeRow("BirthDate"), _
|
||||
employeeRow("LastName"), _
|
||||
employeeRow("FirstName"))
|
||||
Next employeeRow
|
||||
|
||||
' Keep the window opened to view the contents.
|
||||
Console.ReadLine()
|
||||
End Sub
|
||||
```
|
||||
|
||||
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _
|
||||
queryString, connectionString)
|
||||
Dim employees As New DataSet
|
||||
adapter.Fill(employees, "Employees")
|
||||
|
||||
' Create a SqlDataReader for use with the Load Method.
|
||||
Dim reader As DataTableReader = employees.GetDataReader()
|
||||
|
||||
' Create an instance of DataTable and assign the first
|
||||
' DataTable in the DataSet.Tables collection to it.
|
||||
Dim dataTableEmp As DataTable = employees.Tables(0)
|
||||
|
||||
' Fill the DataTable with data by calling Load and
|
||||
' passing the SqlDataReader.
|
||||
dataTableEmp.Load(reader, LoadOption.OverwriteRow)
|
||||
|
||||
' Loop through the rows collection and display the values
|
||||
' in the console window.
|
||||
Dim employeeRow As DataRow
|
||||
For Each employeeRow In dataTableEmp.Rows
|
||||
Console.WriteLine("{0:MM\\dd\\yyyy}" & ControlChars.Tab & _
|
||||
"{1}, {2}", _
|
||||
employeeRow("BirthDate"), _
|
||||
employeeRow("LastName"), _
|
||||
employeeRow("FirstName"))
|
||||
Next employeeRow
|
||||
|
||||
' Keep the window opened to view the contents.
|
||||
Console.ReadLine()
|
||||
End Sub
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Manipulating Data in a DataTable](manipulating-data-in-a-datatable.md)
|
||||
|
|
|
@ -2,52 +2,51 @@
|
|||
description: "Learn more about: Distributed Transactions"
|
||||
title: "Distributed Transactions"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 718b257c-bcb2-408e-b004-a7b0adb1c176
|
||||
---
|
||||
# Distributed Transactions
|
||||
# Distributed transactions
|
||||
|
||||
A transaction is a set of related tasks that either succeeds (commit) or fails (abort) as a unit, among other things. A *distributed transaction* is a transaction that affects several resources. For a distributed transaction to commit, all participants must guarantee that any change to data will be permanent. Changes must persist despite system crashes or other unforeseen events. If even a single participant fails to make this guarantee, the entire transaction fails, and any changes to data within the scope of the transaction are rolled back.
|
||||
|
||||
A transaction is a set of related tasks that either succeeds (commit) or fails (abort) as a unit, among other things. A *distributed transaction* is a transaction that affects several resources. For a distributed transaction to commit, all participants must guarantee that any change to data will be permanent. Changes must persist despite system crashes or other unforeseen events. If even a single participant fails to make this guarantee, the entire transaction fails, and any changes to data within the scope of the transaction are rolled back.
|
||||
|
||||
> [!NOTE]
|
||||
> An exception will be thrown if you attempt to commit or roll back a transaction if a `DataReader` is started while the transaction is active.
|
||||
|
||||
## Working with System.Transactions
|
||||
> An exception will be thrown if you attempt to commit or roll back a transaction if a `DataReader` is started while the transaction is active.
|
||||
|
||||
## Working with System.Transactions
|
||||
|
||||
In .NET Framework, distributed transactions are managed through the API in the <xref:System.Transactions> namespace. The <xref:System.Transactions> API will delegate distributed transaction handling to a transaction monitor such as the Microsoft Distributed Transaction Coordinator (MS DTC) when multiple persistent resource managers are involved. For more information, see [Transaction Fundamentals](../transactions/transaction-fundamentals.md).
|
||||
|
||||
ADO.NET 2.0 introduced support for enlisting in a distributed transaction using the `EnlistTransaction` method, which enlists a connection in a <xref:System.Transactions.Transaction> instance. In previous versions of ADO.NET, explicit enlistment in distributed transactions was performed using the `EnlistDistributedTransaction` method of a connection to enlist a connection in a <xref:System.EnterpriseServices.ITransaction> instance, which is supported for backwards compatibility. For more information on Enterprise Services transactions, see [Interoperability with Enterprise Services and COM+ Transactions](../transactions/interoperability-with-enterprise-services-and-com-transactions.md).
|
||||
|
||||
When using a <xref:System.Transactions> transaction with the .NET Framework Provider for SQL Server against a SQL Server database, a lightweight <xref:System.Transactions.Transaction> will automatically be used. The transaction can then be promoted to a full distributed transaction on an as-needed basis. For more information, see [System.Transactions Integration with SQL Server](system-transactions-integration-with-sql-server.md).
|
||||
|
||||
In the .NET Framework, distributed transactions are managed through the API in the <xref:System.Transactions> namespace. The <xref:System.Transactions> API will delegate distributed transaction handling to a transaction monitor such as the Microsoft Distributed Transaction Coordinator (MS DTC) when multiple persistent resource managers are involved. For more information, see [Transaction Fundamentals](../transactions/transaction-fundamentals.md).
|
||||
|
||||
ADO.NET 2.0 introduced support for enlisting in a distributed transaction using the `EnlistTransaction` method, which enlists a connection in a <xref:System.Transactions.Transaction> instance. In previous versions of ADO.NET, explicit enlistment in distributed transactions was performed using the `EnlistDistributedTransaction` method of a connection to enlist a connection in a <xref:System.EnterpriseServices.ITransaction> instance, which is supported for backwards compatibility. For more information on Enterprise Services transactions, see [Interoperability with Enterprise Services and COM+ Transactions](../transactions/interoperability-with-enterprise-services-and-com-transactions.md).
|
||||
|
||||
When using a <xref:System.Transactions> transaction with the .NET Framework Provider for SQL Server against a SQL Server database, a lightweight <xref:System.Transactions.Transaction> will automatically be used. The transaction can then be promoted to a full distributed transaction on an as-needed basis. For more information, see [System.Transactions Integration with SQL Server](system-transactions-integration-with-sql-server.md).
|
||||
|
||||
> [!NOTE]
|
||||
> The maximum number of distributed transactions that an Oracle database can participate in at one time is set to 10 by default. After the 10th transaction when connected to an Oracle database, an exception is thrown. Oracle does not support `DDL` inside of a distributed transaction.
|
||||
|
||||
## Automatically Enlisting in a Distributed Transaction
|
||||
> The maximum number of distributed transactions that an Oracle database can participate in at one time is set to 10 by default. After the 10th transaction when connected to an Oracle database, an exception is thrown. Oracle does not support `DDL` inside of a distributed transaction.
|
||||
|
||||
Automatic enlistment is the default (and preferred) way of integrating ADO.NET connections with `System.Transactions`. A connection object will automatically enlist in an existing distributed transaction if it determines that a transaction is active, which, in `System.Transaction` terms, means that `Transaction.Current` is not null. Automatic transaction enlistment occurs when the connection is opened. It will not happen after that even if a command is executed inside of a transaction scope. You can disable auto-enlistment in existing transactions by specifying `Enlist=false` as a connection string parameter for a <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType>, or `OLE DB Services=-7` as a connection string parameter for an <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A?displayProperty=nameWithType>. For more information on Oracle and ODBC connection string parameters, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A?displayProperty=nameWithType> and <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A?displayProperty=nameWithType>.
|
||||
|
||||
## Manually Enlisting in a Distributed Transaction
|
||||
## Automatically Enlisting in a Distributed Transaction
|
||||
|
||||
Automatic enlistment is the default (and preferred) way of integrating ADO.NET connections with `System.Transactions`. A connection object will automatically enlist in an existing distributed transaction if it determines that a transaction is active, which, in `System.Transaction` terms, means that `Transaction.Current` is not null. Automatic transaction enlistment occurs when the connection is opened. It will not happen after that even if a command is executed inside of a transaction scope. You can disable auto-enlistment in existing transactions by specifying `Enlist=false` as a connection string parameter for a <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A?displayProperty=nameWithType>, or `OLE DB Services=-7` as a connection string parameter for an <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A?displayProperty=nameWithType>. For more information on Oracle and ODBC connection string parameters, see <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A?displayProperty=nameWithType> and <xref:System.Data.Odbc.OdbcConnection.ConnectionString%2A?displayProperty=nameWithType>.
|
||||
|
||||
## Manually Enlisting in a Distributed Transaction
|
||||
|
||||
If auto-enlistment is disabled or you need to enlist a transaction that was started after the connection was opened, you can enlist in an existing distributed transaction using the `EnlistTransaction` method of the <xref:System.Data.Common.DbConnection> object for the provider you are working with. Enlisting in an existing distributed transaction ensures that, if the transaction is committed or rolled back, modifications made by the code at the data source will be committed or rolled back as well.
|
||||
|
||||
Enlisting in distributed transactions is particularly applicable when pooling business objects. If a business object is pooled with an open connection, automatic transaction enlistment only occurs when that connection is opened. If multiple transactions are performed using the pooled business object, the open connection for that object will not automatically enlist in newly initiated transactions. In this case, you can disable automatic transaction enlistment for the connection and enlist the connection in transactions using `EnlistTransaction`.
|
||||
|
||||
`EnlistTransaction` takes a single argument of type <xref:System.Transactions.Transaction> that is a reference to the existing transaction. After calling the connection's `EnlistTransaction` method, all modifications made at the data source using the connection are included in the transaction. Passing a null value unenlists the connection from its current distributed transaction enlistment. Note that the connection must be opened before calling `EnlistTransaction`.
|
||||
|
||||
If auto-enlistment is disabled or you need to enlist a transaction that was started after the connection was opened, you can enlist in an existing distributed transaction using the `EnlistTransaction` method of the <xref:System.Data.Common.DbConnection> object for the provider you are working with. Enlisting in an existing distributed transaction ensures that, if the transaction is committed or rolled back, modifications made by the code at the data source will be committed or rolled back as well.
|
||||
|
||||
Enlisting in distributed transactions is particularly applicable when pooling business objects. If a business object is pooled with an open connection, automatic transaction enlistment only occurs when that connection is opened. If multiple transactions are performed using the pooled business object, the open connection for that object will not automatically enlist in newly initiated transactions. In this case, you can disable automatic transaction enlistment for the connection and enlist the connection in transactions using `EnlistTransaction`.
|
||||
|
||||
`EnlistTransaction` takes a single argument of type <xref:System.Transactions.Transaction> that is a reference to the existing transaction. After calling the connection's `EnlistTransaction` method, all modifications made at the data source using the connection are included in the transaction. Passing a null value unenlists the connection from its current distributed transaction enlistment. Note that the connection must be opened before calling `EnlistTransaction`.
|
||||
|
||||
> [!NOTE]
|
||||
> Once a connection is explicitly enlisted on a transaction, it cannot be un-enlisted or enlisted in another transaction until the first transaction finishes.
|
||||
|
||||
> Once a connection is explicitly enlisted on a transaction, it cannot be un-enlisted or enlisted in another transaction until the first transaction finishes.
|
||||
|
||||
> [!CAUTION]
|
||||
> `EnlistTransaction` throws an exception if the connection has already begun a transaction using the connection's <xref:System.Data.Common.DbConnection.BeginTransaction%2A> method. However, if the transaction is a local transaction started at the data source (for example, executing the BEGIN TRANSACTION statement explicitly using a <xref:System.Data.SqlClient.SqlCommand>), `EnlistTransaction` will roll back the local transaction and enlist in the existing distributed transaction as requested. You will not receive notice that the local transaction was rolled back, and must manage any local transactions not started using <xref:System.Data.Common.DbConnection.BeginTransaction%2A>. If you are using the .NET Framework Data Provider for SQL Server (`SqlClient`) with SQL Server, an attempt to enlist will throw an exception. All other cases will go undetected.
|
||||
|
||||
## Promotable Transactions in SQL Server
|
||||
> `EnlistTransaction` throws an exception if the connection has already begun a transaction using the connection's <xref:System.Data.Common.DbConnection.BeginTransaction%2A> method. However, if the transaction is a local transaction started at the data source (for example, executing the BEGIN TRANSACTION statement explicitly using a <xref:System.Data.SqlClient.SqlCommand>), `EnlistTransaction` will roll back the local transaction and enlist in the existing distributed transaction as requested. You will not receive notice that the local transaction was rolled back, and must manage any local transactions not started using <xref:System.Data.Common.DbConnection.BeginTransaction%2A>. If you are using the .NET Framework Data Provider for SQL Server (`SqlClient`) with SQL Server, an attempt to enlist will throw an exception. All other cases will go undetected.
|
||||
|
||||
SQL Server supports promotable transactions in which a local lightweight transaction can be automatically promoted to a distributed transaction only if it is required. A promotable transaction does not invoke the added overhead of a distributed transaction unless the added overhead is required. For more information and a code sample, see [System.Transactions Integration with SQL Server](system-transactions-integration-with-sql-server.md).
|
||||
|
||||
## Configuring Distributed Transactions
|
||||
## Promotable Transactions in SQL Server
|
||||
|
||||
SQL Server supports promotable transactions in which a local lightweight transaction can be automatically promoted to a distributed transaction only if it is required. A promotable transaction does not invoke the added overhead of a distributed transaction unless the added overhead is required. For more information and a code sample, see [System.Transactions Integration with SQL Server](system-transactions-integration-with-sql-server.md).
|
||||
|
||||
## Configuring Distributed Transactions
|
||||
|
||||
You may need to enable the MS DTC over the network in order to use distributed transactions. If have the Windows Firewall enabled, you must allow the MS DTC service to use the network or open the MS DTC port.
|
||||
|
||||
You may need to enable the MS DTC over the network in order to use distributed transactions. If have the Windows Firewall enabled, you must allow the MS DTC service to use the network or open the MS DTC port.
|
||||
|
||||
## See also
|
||||
|
||||
- [Transactions and Concurrency](transactions-and-concurrency.md)
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
---
|
||||
description: "Learn more about: Establishing the Connection"
|
||||
description: "Learn more about establishing a connection to SQL Server using the .NET Framework Data Provider for SQL Server."
|
||||
title: "Establishing the Connection"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 3af512f3-87d9-4005-9e2f-abb1060ff43f
|
||||
---
|
||||
# Establishing the Connection
|
||||
# Establish a connection
|
||||
|
||||
To connect to Microsoft SQL Server, use the <xref:System.Data.SqlClient.SqlConnection> object of the .NET Framework Data Provider for SQL Server. To connect to an OLE DB data source, use the <xref:System.Data.OleDb.OleDbConnection> object of the .NET Framework Data Provider for OLE DB. To connect to an ODBC data source, use the <xref:System.Data.Odbc.OdbcConnection> object of the .NET Framework Data Provider for ODBC. To connect to an Oracle data source, use the <xref:System.Data.OracleClient.OracleConnection> object of the .NET Framework Data Provider for Oracle. For securely storing and retrieving connection strings, see [Protecting Connection Information](protecting-connection-information.md).
|
||||
|
||||
|
@ -23,7 +22,7 @@ To connect to Microsoft SQL Server, use the <xref:System.Data.SqlClient.SqlConne
|
|||
> [!NOTE]
|
||||
> Login and logout events will not be raised on the server when a connection is fetched from or returned to the connection pool, because the connection is not actually closed when it is returned to the connection pool. For more information, see [SQL Server Connection Pooling (ADO.NET)](sql-server-connection-pooling.md).
|
||||
|
||||
## Connecting to SQL Server
|
||||
## Connect to SQL Server
|
||||
|
||||
The .NET Framework Data Provider for SQL Server supports a connection string format that is similar to the OLE DB (ADO) connection string format. For valid string format names and values, see the <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A> property of the <xref:System.Data.SqlClient.SqlConnection> object. You can also use the <xref:System.Data.SqlClient.SqlConnectionStringBuilder> class to create syntactically valid connection strings at run time. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
|
||||
|
@ -52,7 +51,7 @@ using (SqlConnection connection = new SqlConnection(connectionString))
|
|||
|
||||
The security identity for ASP.NET applications can be set to one of several different options. To better understand the security identity that an ASP.NET application uses when connecting to SQL Server, see [ASP.NET Impersonation](/previous-versions/aspnet/xh507fc5(v=vs.100)), [ASP.NET Authentication](/previous-versions/aspnet/eeyk640h(v=vs.100)), and [How to: Access SQL Server Using Windows Integrated Security](/previous-versions/aspnet/bsz5788z(v=vs.100)).
|
||||
|
||||
## Connecting to an OLE DB Data Source
|
||||
## Connect to an OLE DB Data Source
|
||||
|
||||
The .NET Framework Data Provider for OLE DB provides connectivity to data sources exposed using OLE DB (through SQLOLEDB, the OLE DB Provider for SQL Server), using the **OleDbConnection** object.
|
||||
|
||||
|
@ -62,7 +61,7 @@ using (SqlConnection connection = new SqlConnection(connectionString))
|
|||
|
||||
- The **URL**, **Remote Provider**, and **Remote Server** keywords are not supported.
|
||||
|
||||
For more information about OLE DB connection strings, see the <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A> topic. You can also use the <xref:System.Data.OleDb.OleDbConnectionStringBuilder> to create connection strings at run time.
|
||||
For more information about OLE DB connection strings, see the <xref:System.Data.OleDb.OleDbConnection.ConnectionString%2A> artcile. You can also use the <xref:System.Data.OleDb.OleDbConnectionStringBuilder> to create connection strings at run time.
|
||||
|
||||
> [!NOTE]
|
||||
> The **OleDbConnection** object does not support setting or retrieving dynamic properties specific to an OLE DB provider. Only properties that can be passed in the connection string for the OLE DB provider are supported.
|
||||
|
@ -91,7 +90,7 @@ using (OleDbConnection connection =
|
|||
|
||||
It is possible to supply connection information for an **OleDbConnection** in a Universal Data Link (UDL) file; however you should avoid doing so. UDL files are not encrypted, and expose connection string information in clear text. Because a UDL file is an external file-based resource to your application, it cannot be secured using the .NET Framework.
|
||||
|
||||
## Connecting to an ODBC Data Source
|
||||
## Connect to an ODBC Data Source
|
||||
|
||||
The .NET Framework Data Provider for ODBC provides connectivity to data sources exposed using ODBC using the **OdbcConnection** object.
|
||||
|
||||
|
@ -117,7 +116,7 @@ using (OdbcConnection connection =
|
|||
}
|
||||
```
|
||||
|
||||
## Connecting to an Oracle Data Source
|
||||
## Connect to an Oracle Data Source
|
||||
|
||||
The .NET Framework Data Provider for Oracle provides connectivity to Oracle data sources using the **OracleConnection** object.
|
||||
|
||||
|
@ -141,8 +140,6 @@ using (OracleConnection connection =
|
|||
connection.Open();
|
||||
// Do work here.
|
||||
}
|
||||
OracleConnection nwindConn = new OracleConnection("Data Source=MyOracleServer;Integrated Security=yes;");
|
||||
nwindConn.Open();
|
||||
```
|
||||
|
||||
## See also
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
---
|
||||
description: "Learn more about: Filling a DataSet Using One or More REF CURSORs"
|
||||
description: "Learn more about filling a DataSet using one or more REF CURSORs by studying a Visual Basic code example."
|
||||
title: "Filling a DataSet Using One or More REF CURSORs"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
- "vb"
|
||||
ms.assetid: 99863e79-5b00-467e-a105-4ffa42de3ff7
|
||||
---
|
||||
# Filling a DataSet Using One or More REF CURSORs
|
||||
# Fill a DataSet Using One or More REF CURSORs
|
||||
|
||||
This Microsoft Visual Basic example executes a PL/SQL stored procedure that returns two REF CURSOR parameters, and fills a <xref:System.Data.DataSet> with the rows that are returned.
|
||||
This Visual Basic example executes a PL/SQL stored procedure that returns two REF CURSOR parameters, and fills a <xref:System.Data.DataSet> with the rows that are returned.
|
||||
|
||||
```vb
|
||||
Private Sub Button1_Click(ByVal sender As Object, _
|
||||
ByVal e As System.EventArgs) Handles Button1.Click
|
||||
|
||||
Dim connString As New String(_
|
||||
"Data Source=Oracle9i;User ID=scott;Password=[PLACEHOLDER];")
|
||||
Dim connString As New String("...")
|
||||
Dim ds As New DataSet()
|
||||
Using conn As New OracleConnection(connString)
|
||||
Dim cmd As New OracleCommand()
|
||||
|
|
|
@ -2,106 +2,103 @@
|
|||
description: "Learn more about: GetSchema and Schema Collections"
|
||||
title: "GetSchema and Schema Collections"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 7ab93b89-1221-427c-84ad-04803b3c64b4
|
||||
---
|
||||
# GetSchema and Schema Collections
|
||||
|
||||
The **Connection** classes in each of the .NET Framework managed providers implement a **GetSchema** method which is used to retrieve schema information about the database that is currently connected, and the schema information returned from the **GetSchema** method comes in the form of a <xref:System.Data.DataTable>. The **GetSchema** method is an overloaded method that provides optional parameters for specifying the schema collection to return, and restricting the amount of information returned.
|
||||
|
||||
## Specifying the Schema Collections
|
||||
The **Connection** classes in each of the .NET Framework managed providers implement a **GetSchema** method that's used to retrieve schema information about the database that is currently connected. The schema information returned from the **GetSchema** method comes in the form of a <xref:System.Data.DataTable>. The **GetSchema** method is an overloaded method that provides optional parameters for specifying the schema collection to return, and for restricting the amount of information returned.
|
||||
|
||||
The first optional parameter of the **GetSchema** method is the collection name which is specified as a string. There are two types of schema collections: common schema collections that are common to all providers, and specific schema collections which are specific to each provider.
|
||||
|
||||
You can query a .NET Framework managed provider to determine the list of supported schema collections by calling the **GetSchema** method with no arguments, or with the schema collection name "MetaDataCollections". This will return a <xref:System.Data.DataTable> with a list of the supported schema collections, the number of restrictions that they each support, and the number of identifier parts that they use.
|
||||
|
||||
### Retrieving Schema Collections Example
|
||||
## Specifying the Schema Collections
|
||||
|
||||
The following examples demonstrate how to use the <xref:System.Data.SqlClient.SqlConnection.GetSchema%2A> method of the .NET Framework Data Provider for the SQL Server <xref:System.Data.SqlClient.SqlConnection> class to retrieve schema information about all of the tables contained in the **AdventureWorks** sample database:
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Module Module1
|
||||
Sub Main()
|
||||
Dim connectionString As String = GetConnectionString()
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
'Connect to the database then retrieve the schema information.
|
||||
connection.Open()
|
||||
Dim table As DataTable = connection.GetSchema("Tables")
|
||||
|
||||
' Display the contents of the table.
|
||||
DisplayData(table)
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Using
|
||||
End Sub
|
||||
|
||||
Private Function GetConnectionString() As String
|
||||
The first optional parameter of the **GetSchema** method is the collection name which is specified as a string. There are two types of schema collections: common schema collections that are common to all providers, and specific schema collections which are specific to each provider.
|
||||
|
||||
You can query a .NET Framework managed provider to determine the list of supported schema collections by calling the **GetSchema** method with no arguments, or with the schema collection name "MetaDataCollections". This will return a <xref:System.Data.DataTable> with a list of the supported schema collections, the number of restrictions that they each support, and the number of identifier parts that they use.
|
||||
|
||||
### Retrieving Schema Collections Example
|
||||
|
||||
The following examples demonstrate how to use the <xref:System.Data.SqlClient.SqlConnection.GetSchema%2A> method of the .NET Framework Data Provider for the SQL Server <xref:System.Data.SqlClient.SqlConnection> class to retrieve schema information about all of the tables contained in the **AdventureWorks** sample database:
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Module Module1
|
||||
Sub Main()
|
||||
Dim connectionString As String = GetConnectionString()
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
'Connect to the database then retrieve the schema information.
|
||||
connection.Open()
|
||||
Dim table As DataTable = connection.GetSchema("Tables")
|
||||
|
||||
' Display the contents of the table.
|
||||
DisplayData(table)
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Using
|
||||
End Sub
|
||||
|
||||
Private Function GetConnectionString() As String
|
||||
' To avoid storing the connection string in your code,
|
||||
' you can retrieve it from a configuration file.
|
||||
Return "Data Source=(local);Database=AdventureWorks;" _
|
||||
& "Integrated Security=true;"
|
||||
End Function
|
||||
|
||||
Private Sub DisplayData(ByVal table As DataTable)
|
||||
For Each row As DataRow In table.Rows
|
||||
For Each col As DataColumn In table.Columns
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row(col))
|
||||
Next
|
||||
Console.WriteLine("============================")
|
||||
Next
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
string connectionString = GetConnectionString();
|
||||
using (SqlConnection connection = new SqlConnection(connectionString))
|
||||
{
|
||||
// Connect to the database then retrieve the schema information.
|
||||
connection.Open();
|
||||
DataTable table = connection.GetSchema("Tables");
|
||||
|
||||
// Display the contents of the table.
|
||||
DisplayData(table);
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return "Data Source=(local);Database=AdventureWorks;" +
|
||||
"Integrated Security=true;";
|
||||
}
|
||||
|
||||
private static void DisplayData(System.Data.DataTable table)
|
||||
{
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
' you can retrieve it from a configuration file.
|
||||
Return "..."
|
||||
End Function
|
||||
|
||||
Private Sub DisplayData(ByVal table As DataTable)
|
||||
For Each row As DataRow In table.Rows
|
||||
For Each col As DataColumn In table.Columns
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row(col))
|
||||
Next
|
||||
Console.WriteLine("============================")
|
||||
Next
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
string connectionString = GetConnectionString();
|
||||
using (SqlConnection connection = new SqlConnection(connectionString))
|
||||
{
|
||||
// Connect to the database then retrieve the schema information.
|
||||
connection.Open();
|
||||
DataTable table = connection.GetSchema("Tables");
|
||||
|
||||
// Display the contents of the table.
|
||||
DisplayData(table);
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return "...";
|
||||
}
|
||||
|
||||
private static void DisplayData(System.Data.DataTable table)
|
||||
{
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Retrieving Database Schema Information](retrieving-database-schema-information.md)
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
---
|
||||
description: "Learn more about: How to: Bind a DataView Object to a Windows Forms DataGridView Control"
|
||||
description: "Learn how to bind a DataView object to a Windows Forms DataGridView control, which provides a powerful and flexible way to display data in a tabular format."
|
||||
title: "How to: Bind a DataView Object to a Windows Forms DataGridView Control"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 2b73d60a-6049-446a-85a7-3e5a68b183e2
|
||||
---
|
||||
# How to: Bind a DataView Object to a Windows Forms DataGridView Control
|
||||
|
||||
The <xref:System.Windows.Forms.DataGridView> control provides a powerful and flexible way to display data in a tabular format. The <xref:System.Windows.Forms.DataGridView> control supports the standard Windows Forms data binding model, so it will bind to <xref:System.Data.DataView> and a variety of other data sources. In most situations, however, you will bind to a <xref:System.Windows.Forms.BindingSource> component that will manage the details of interacting with the data source.
|
||||
|
||||
For more information about the <xref:System.Windows.Forms.DataGridView> control, see [DataGridView Control Overview](/dotnet/desktop/winforms/controls/datagridview-control-overview-windows-forms).
|
||||
|
||||
### To connect a DataGridView control to a DataView
|
||||
|
||||
1. Implement a method to handle the details of retrieving data from a database. The following code example implements a `GetData` method that initializes a <xref:System.Data.SqlClient.SqlDataAdapter> component and uses it to fill a <xref:System.Data.DataSet>. Be sure to set the `connectionString` variable to a value that is appropriate for your database. You will need access to a server with the AdventureWorks SQL Server sample database installed.
|
||||
|
||||
The <xref:System.Windows.Forms.DataGridView> control provides a powerful and flexible way to display data in a tabular format. The <xref:System.Windows.Forms.DataGridView> control supports the standard Windows Forms data binding model, so it will bind to <xref:System.Data.DataView> and a variety of other data sources. In most situations, however, you will bind to a <xref:System.Windows.Forms.BindingSource> component that will manage the details of interacting with the data source.
|
||||
|
||||
For more information about the <xref:System.Windows.Forms.DataGridView> control, see [DataGridView Control Overview](/dotnet/desktop/winforms/controls/datagridview-control-overview-windows-forms).
|
||||
|
||||
## To connect a DataGridView control to a DataView
|
||||
|
||||
1. Implement a method to handle the details of retrieving data from a database. The following code example implements a `GetData` method that initializes a <xref:System.Data.SqlClient.SqlDataAdapter> component and uses it to fill a <xref:System.Data.DataSet>. Be sure to set the `connectionString` variable to a value that's appropriate for your database. You will need access to a server with the AdventureWorks SQL Server sample database installed.
|
||||
|
||||
[!code-csharp[DP DataViewWinForms Sample#LDVSample1GetData](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/CS/Form1.cs#ldvsample1getdata)]
|
||||
[!code-vb[DP DataViewWinForms Sample#LDVSample1GetData](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/VB/Form1.vb#ldvsample1getdata)]
|
||||
|
||||
2. In the <xref:System.Windows.Forms.Form.Load> event handler of your form, bind the <xref:System.Windows.Forms.DataGridView> control to the <xref:System.Windows.Forms.BindingSource> component and call the `GetData` method to retrieve the data from the database. The <xref:System.Data.DataView> is created from a LINQ to DataSet query over the Contact <xref:System.Data.DataTable> and is then bound to the <xref:System.Windows.Forms.BindingSource> component.
|
||||
|
||||
[!code-vb[DP DataViewWinForms Sample#LDVSample1GetData](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/VB/Form1.vb#ldvsample1getdata)]
|
||||
|
||||
2. In the <xref:System.Windows.Forms.Form.Load> event handler of your form, bind the <xref:System.Windows.Forms.DataGridView> control to the <xref:System.Windows.Forms.BindingSource> component and call the `GetData` method to retrieve the data from the database. The <xref:System.Data.DataView> is created from a LINQ to DataSet query over the Contact <xref:System.Data.DataTable> and is then bound to the <xref:System.Windows.Forms.BindingSource> component.
|
||||
|
||||
[!code-csharp[DP DataViewWinForms Sample#LDVSample1FormLoad](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/CS/Form1.cs#ldvsample1formload)]
|
||||
[!code-vb[DP DataViewWinForms Sample#LDVSample1FormLoad](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/VB/Form1.vb#ldvsample1formload)]
|
||||
|
||||
[!code-vb[DP DataViewWinForms Sample#LDVSample1FormLoad](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DP DataViewWinForms Sample/VB/Form1.vb#ldvsample1formload)]
|
||||
|
||||
## See also
|
||||
|
||||
- [Data Binding and LINQ to DataSet](data-binding-and-linq-to-dataset.md)
|
||||
|
|
|
@ -1,102 +1,103 @@
|
|||
---
|
||||
title: "Obtaining a DbProviderFactory"
|
||||
description: Learn how to obtain a DbProviderFactory from the DbProviderFactories class to work with specific data sources in the .NET Framework.
|
||||
description: Learn how to obtain a DbProviderFactory from the DbProviderFactories class to work with specific data sources in .NET Framework.
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: a16e4a4d-6a5b-45db-8635-19570e4572ae
|
||||
---
|
||||
# Obtaining a DbProviderFactory
|
||||
|
||||
The process of obtaining a <xref:System.Data.Common.DbProviderFactory> involves passing information about a data provider to the <xref:System.Data.Common.DbProviderFactories> class. Based on this information, the <xref:System.Data.Common.DbProviderFactories.GetFactory%2A> method creates a strongly typed provider factory. For example, to create a <xref:System.Data.SqlClient.SqlClientFactory>, you can pass `GetFactory` a string with the provider name specified as "System.Data.SqlClient". The other overload of `GetFactory` takes a <xref:System.Data.DataRow>. Once you create the provider factory, you can then use its methods to create additional objects. Some of the methods of a `SqlClientFactory` include <xref:System.Data.SqlClient.SqlClientFactory.CreateConnection%2A>, <xref:System.Data.SqlClient.SqlClientFactory.CreateCommand%2A>, and <xref:System.Data.SqlClient.SqlClientFactory.CreateDataAdapter%2A>.
|
||||
|
||||
> [!NOTE]
|
||||
> The .NET Framework <xref:System.Data.OracleClient.OracleClientFactory>, <xref:System.Data.Odbc.OdbcFactory>, and <xref:System.Data.OleDb.OleDbFactory> classes also provide similar functionality.
|
||||
|
||||
## Registering DbProviderFactories
|
||||
The process of obtaining a <xref:System.Data.Common.DbProviderFactory> involves passing information about a data provider to the <xref:System.Data.Common.DbProviderFactories> class. Based on this information, the <xref:System.Data.Common.DbProviderFactories.GetFactory%2A> method creates a strongly typed provider factory. For example, to create a <xref:System.Data.SqlClient.SqlClientFactory>, you can pass `GetFactory` a string with the provider name specified as "System.Data.SqlClient". The other overload of `GetFactory` takes a <xref:System.Data.DataRow>. Once you create the provider factory, you can then use its methods to create additional objects. Some of the methods of a `SqlClientFactory` include <xref:System.Data.SqlClient.SqlClientFactory.CreateConnection%2A>, <xref:System.Data.SqlClient.SqlClientFactory.CreateCommand%2A>, and <xref:System.Data.SqlClient.SqlClientFactory.CreateDataAdapter%2A>.
|
||||
|
||||
Each .NET Framework data provider that supports a factory-based class registers configuration information in the **DbProviderFactories** section of the **machine.config** file on the local computer. The following configuration file fragment shows the syntax and format for <xref:System.Data.SqlClient>.
|
||||
|
||||
```xml
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<add name="SqlClient Data Provider"
|
||||
> [!NOTE]
|
||||
> The .NET Framework <xref:System.Data.OracleClient.OracleClientFactory>, <xref:System.Data.Odbc.OdbcFactory>, and <xref:System.Data.OleDb.OleDbFactory> classes also provide similar functionality.
|
||||
|
||||
## Registering DbProviderFactories
|
||||
|
||||
Each .NET Framework data provider that supports a factory-based class registers configuration information in the **DbProviderFactories** section of the **machine.config** file on the local computer. The following configuration file fragment shows the syntax and format for <xref:System.Data.SqlClient>.
|
||||
|
||||
```xml
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<add name="SqlClient Data Provider"
|
||||
invariant="System.Data.SqlClient"
|
||||
description=".Net Framework Data Provider for SqlServer"
|
||||
type="System.Data.SqlClient.SqlClientFactory, System.Data,
|
||||
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
||||
/>
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
```
|
||||
|
||||
The **invariant** attribute identifies the underlying data provider. This three-part naming syntax is also used when creating a new factory and for identifying the provider in an application configuration file so that the provider name, along with its associated connection string, can be retrieved at run time.
|
||||
|
||||
## Retrieving Provider Information
|
||||
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
|
||||
/>
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
```
|
||||
|
||||
You can retrieve information about all of the data providers installed on the local computer by using the <xref:System.Data.Common.DbProviderFactories.GetFactoryClasses%2A> method. It returns a <xref:System.Data.DataTable> named **DbProviderFactories** that contains the columns described in the following table.
|
||||
|
||||
|Column ordinal|Column name|Example output|Description|
|
||||
|--------------------|-----------------|--------------------|-----------------|
|
||||
|0|**Name**|SqlClient Data Provider|Readable name for the data provider|
|
||||
|1|**Description**|.Net Framework Data Provider for SqlServer|Readable description of the data provider|
|
||||
|2|**InvariantName**|System.Data.SqlClient|Name that can be used programmatically to refer to the data provider|
|
||||
|3|**AssemblyQualifiedName**|System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|Fully qualified name of the factory class, which contains enough information to instantiate the object|
|
||||
|
||||
This `DataTable` can be used to enable a user to select a <xref:System.Data.DataRow> at run time. The selected `DataRow` can then be passed to the <xref:System.Data.Common.DbProviderFactories.GetFactory%2A> method to create a strongly typed <xref:System.Data.Common.DbProviderFactory>. A selected <xref:System.Data.DataRow> can be passed to the `GetFactory` method to create the desired `DbProviderFactory` object.
|
||||
|
||||
## Listing the Installed Provider Factory Classes
|
||||
The **invariant** attribute identifies the underlying data provider. This three-part naming syntax is also used when creating a new factory and for identifying the provider in an application configuration file so that the provider name, along with its associated connection string, can be retrieved at run time.
|
||||
|
||||
## Retrieving Provider Information
|
||||
|
||||
You can retrieve information about all of the data providers installed on the local computer by using the <xref:System.Data.Common.DbProviderFactories.GetFactoryClasses%2A> method. It returns a <xref:System.Data.DataTable> named **DbProviderFactories** that contains the columns described in the following table.
|
||||
|
||||
|Column ordinal|Column name|Example output|Description|
|
||||
|--------------------|-----------------|--------------------|-----------------|
|
||||
|0|**Name**|SqlClient Data Provider|Readable name for the data provider|
|
||||
|1|**Description**|.Net Framework Data Provider for SqlServer|Readable description of the data provider|
|
||||
|2|**InvariantName**|System.Data.SqlClient|Name that can be used programmatically to refer to the data provider|
|
||||
|3|**AssemblyQualifiedName**|System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089|Fully qualified name of the factory class, which contains enough information to instantiate the object|
|
||||
|
||||
This `DataTable` can be used to enable a user to select a <xref:System.Data.DataRow> at run time. The selected `DataRow` can then be passed to the <xref:System.Data.Common.DbProviderFactories.GetFactory%2A> method to create a strongly typed <xref:System.Data.Common.DbProviderFactory>. A selected <xref:System.Data.DataRow> can be passed to the `GetFactory` method to create the desired `DbProviderFactory` object.
|
||||
|
||||
## Listing the Installed Provider Factory Classes
|
||||
|
||||
This example demonstrates how to use the <xref:System.Data.Common.DbProviderFactories.GetFactoryClasses%2A> method to return a <xref:System.Data.DataTable> containing information about the installed providers. The code iterates through each row in the `DataTable`, displaying information for each installed provider in the console window.
|
||||
|
||||
This example demonstrates how to use the <xref:System.Data.Common.DbProviderFactories.GetFactoryClasses%2A> method to return a <xref:System.Data.DataTable> containing information about the installed providers. The code iterates through each row in the `DataTable`, displaying information for each installed provider in the console window.
|
||||
|
||||
[!code-csharp[DataWorks DbProviderFactories#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks DbProviderFactories/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks DbProviderFactories#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks DbProviderFactories/VB/source.vb#1)]
|
||||
|
||||
## Using Application Configuration Files to Store Factory Information
|
||||
[!code-vb[DataWorks DbProviderFactories#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks DbProviderFactories/VB/source.vb#1)]
|
||||
|
||||
The design pattern used for working with factories entails storing provider and connection string information in an application configuration file, such as **app.config** for a Windows application, and **web.config** for an ASP.NET application.
|
||||
|
||||
The following configuration file fragment demonstrates how to save two named connection strings, "NorthwindSQL" for a connection to the Northwind database in SQL Server, and "NorthwindAccess" for a connection to the Northwind database in Access/Jet. The **invariant** name is used for the **providerName** attribute.
|
||||
|
||||
```xml
|
||||
<configuration>
|
||||
<connectionStrings>
|
||||
<clear/>
|
||||
## Using Application Configuration Files to Store Factory Information
|
||||
|
||||
The design pattern used for working with factories entails storing provider and connection string information in an application configuration file, such as **app.config** for a Windows application, and **web.config** for an ASP.NET application.
|
||||
|
||||
The following configuration file fragment demonstrates how to save two named connection strings: "NorthwindSQL" for a connection to the Northwind database in SQL Server, and "NorthwindAccess" for a connection to the Northwind database in Access/Jet. The **invariant** name is used for the **providerName** attribute.
|
||||
|
||||
```xml
|
||||
<configuration>
|
||||
<connectionStrings>
|
||||
<clear/>
|
||||
<add name="NorthwindSQL"
|
||||
providerName="System.Data.SqlClient"
|
||||
connectionString=
|
||||
"Data Source=MSSQL1;Initial Catalog=Northwind;Integrated Security=true"
|
||||
/>
|
||||
|
||||
connectionString=
|
||||
"Data Source=MSSQL1;Initial Catalog=Northwind;Integrated Security=true"
|
||||
/>
|
||||
|
||||
<add name="NorthwindAccess"
|
||||
providerName="System.Data.OleDb"
|
||||
connectionString=
|
||||
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Northwind.mdb;"
|
||||
/>
|
||||
</connectionStrings>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
### Retrieving a Connection String by Provider Name
|
||||
connectionString=
|
||||
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Data\Northwind.mdb;"
|
||||
/>
|
||||
</connectionStrings>
|
||||
</configuration>
|
||||
```
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Retrieve a Connection String by Provider Name
|
||||
|
||||
In order to create a provider factory, you must supply a connection string as well as the provider name. This example demonstrates how to retrieve a connection string from an application configuration file by passing the provider name in the invariant format "*System.Data.ProviderName*". The code iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection>. It returns the <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A> on success; otherwise `null` (`Nothing` in Visual Basic). If there are multiple entries for a provider, the first one found is returned. For more information and examples of retrieving connection strings from configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
|
||||
In order to create a provider factory, you must supply a connection string as well as the provider name. This example demonstrates how to retrieve a connection string from an application configuration file by passing the provider name in the invariant format "*System.Data.ProviderName*". The code iterates through the <xref:System.Configuration.ConnectionStringSettingsCollection>. It returns the <xref:System.Configuration.ConnectionStringSettings.ProviderName%2A> on success; otherwise `null` (`Nothing` in Visual Basic). If there are multiple entries for a provider, the first one found is returned. For more information and examples of retrieving connection strings from configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
|
||||
> [!NOTE]
|
||||
> A reference to `System.Configuration.dll` is required in order for the code to run.
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/VB/source.vb#1)]
|
||||
|
||||
## Creating the DbProviderFactory and DbConnection
|
||||
> A reference to `System.Configuration.dll` is required in order for the code to run.
|
||||
|
||||
[!code-csharp[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks ConnectionStringSettings.RetrieveFromConfigByProvider/VB/source.vb#1)]
|
||||
|
||||
## Creating the DbProviderFactory and DbConnection
|
||||
|
||||
This example demonstrates how to create a <xref:System.Data.Common.DbProviderFactory> and <xref:System.Data.Common.DbConnection> object by passing it the provider name in the format "*System.Data.ProviderName*" and a connection string. A `DbConnection` object is returned on success; `null` (`Nothing` in Visual Basic) on any error.
|
||||
|
||||
The code obtains the `DbProviderFactory` by calling <xref:System.Data.Common.DbProviderFactories.GetFactory%2A>. Then the <xref:System.Data.Common.DbProviderFactory.CreateConnection%2A> method creates the <xref:System.Data.Common.DbConnection> object and the <xref:System.Data.Common.DbConnection.ConnectionString%2A> property is set to the connection string.
|
||||
|
||||
This example demonstrates how to create a <xref:System.Data.Common.DbProviderFactory> and <xref:System.Data.Common.DbConnection> object by passing it the provider name in the format "*System.Data.ProviderName*" and a connection string. A `DbConnection` object is returned on success; `null` (`Nothing` in Visual Basic) on any error.
|
||||
|
||||
The code obtains the `DbProviderFactory` by calling <xref:System.Data.Common.DbProviderFactories.GetFactory%2A>. Then the <xref:System.Data.Common.DbProviderFactory.CreateConnection%2A> method creates the <xref:System.Data.Common.DbConnection> object and the <xref:System.Data.Common.DbConnection.ConnectionString%2A> property is set to the connection string.
|
||||
|
||||
[!code-csharp[DataWorks DbProviderFactories.GetFactory#1](../../../../samples/snippets/csharp/VS_Snippets_ADO.NET/DataWorks DbProviderFactories.GetFactory/CS/source.cs#1)]
|
||||
[!code-vb[DataWorks DbProviderFactories.GetFactory#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks DbProviderFactories.GetFactory/VB/source.vb#1)]
|
||||
|
||||
[!code-vb[DataWorks DbProviderFactories.GetFactory#1](../../../../samples/snippets/visualbasic/VS_Snippets_ADO.NET/DataWorks DbProviderFactories.GetFactory/VB/source.vb#1)]
|
||||
|
||||
## See also
|
||||
|
||||
- [DbProviderFactories](dbproviderfactories.md)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
---
|
||||
description: "Learn more about: OLE DB, ODBC, and Oracle connection pooling"
|
||||
description: "Learn more about: OLE DB, ODBC, and Oracle connection pooling, which can significantly enhance the performance and scalability of your application."
|
||||
title: "OLE DB, ODBC, and Oracle Connection Pooling"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 2bd83b1e-3ea9-43c4-bade-d9cdb9bbbb04
|
||||
---
|
||||
# OLE DB, ODBC, and Oracle connection pooling
|
||||
|
||||
Pooling connections can significantly enhance the performance and scalability of your application. This section discusses connection pooling for the .NET Framework data providers for OLE DB, ODBC, and Oracle.
|
||||
When you pool connections, you can significantly enhance the performance and scalability of your application. This article discusses connection pooling for the .NET Framework data providers for OLE DB, ODBC, and Oracle.
|
||||
|
||||
## OleDb
|
||||
|
||||
|
@ -16,19 +15,21 @@ The .NET Framework Data Provider for OLE DB automatically pools connections usin
|
|||
Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=SSPI;
|
||||
```
|
||||
|
||||
We recommend that you always close or dispose of a connection when you are finished using it in order to return the connection to the pool. Connections that are not explicitly closed may not get returned to the pool. For example, a connection that has gone out of scope but that has not been explicitly closed will only be returned to the connection pool if the maximum pool size has been reached and the connection is still valid.
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
We recommend that you always close or dispose of a connection when you're finished using it in order to return the connection to the pool. Connections that aren't explicitly closed might not get returned to the pool. For example, a connection that has gone out of scope but that has not been explicitly closed will only be returned to the connection pool if the maximum pool size is reached and the connection is still valid.
|
||||
|
||||
For more information about OLE DB session or resource pooling, as well as how to disable pooling by overriding OLE DB provider service defaults, see the [OLE DB Programmer's Guide](/previous-versions/windows/desktop/ms713643(v=vs.85)).
|
||||
|
||||
## ODBC
|
||||
|
||||
Connection pooling for the .NET Framework Data Provider for ODBC is managed by the ODBC Driver Manager that is used for the connection, and is not affected by the .NET Framework Data Provider for ODBC.
|
||||
Connection pooling for the .NET Framework Data Provider for ODBC is managed by the ODBC Driver Manager that's used for the connection, and is not affected by the .NET Framework Data Provider for ODBC.
|
||||
|
||||
To enable or disable connection pooling, open **ODBC Data Source Administrator** in the Administrative Tools folder of Control Panel. The **Connection Pooling** tab allows you to specify connection pooling parameters for each ODBC driver installed. Connection pooling changes for a specific ODBC driver affect all applications that use that ODBC driver.
|
||||
|
||||
## OracleClient
|
||||
|
||||
The .NET Framework Data Provider for Oracle provides connection pooling automatically for your ADO.NET client application. You can also supply several connection string modifiers to control connection pooling behavior (see "Controlling Connection Pooling with Connection String Keywords," later in this topic).
|
||||
The .NET Framework Data Provider for Oracle provides connection pooling automatically for your ADO.NET client application. You can also supply several connection string modifiers to control connection pooling behavior (see "Controlling Connection Pooling with Connection String Keywords," later in this article).
|
||||
|
||||
### Create and assign pools
|
||||
|
||||
|
@ -36,7 +37,7 @@ Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=S
|
|||
|
||||
Once created, connection pools are not destroyed until the active process ends. Maintaining inactive or empty pools uses very few system resources.
|
||||
|
||||
### Connection Addition
|
||||
### Connection addition
|
||||
|
||||
A connection pool is created for each unique connection string. When a pool is created, multiple connection objects are created and added to the pool so that the minimum pool size requirement is satisfied. Connections are added to the pool as needed, up to the maximum pool size.
|
||||
|
||||
|
@ -44,7 +45,7 @@ Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=S
|
|||
|
||||
If the maximum pool size has been reached and no usable connection is available, the request is queued. The connection pooler satisfies these requests by reallocating connections as they are released back into the pool. Connections are released back into the pool when they are closed or disposed.
|
||||
|
||||
### Connection Removal
|
||||
### Connection removal
|
||||
|
||||
The connection pooler removes a connection from the pool after it has been idle for an extended period of time or if the pooler detects that the connection with the server has been severed. This can be detected only after attempting to communicate with the server. If a connection is found that is no longer connected to the server, it is marked as invalid. The connection pooler periodically scans connection pools looking for objects that have been released to the pool and are marked as invalid. These connections are then permanently removed.
|
||||
|
||||
|
@ -52,20 +53,20 @@ Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=S
|
|||
|
||||
Do not call `Close` or `Dispose` on a `Connection`, a `DataReader`, or any other managed object in the `Finalize` method of your class. In a finalizer, only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a `Finalize` method in your class definition. For more information, see [Garbage Collection](../../../standard/garbage-collection/index.md).
|
||||
|
||||
### Transaction Support
|
||||
### Transaction support
|
||||
|
||||
Connections are drawn from the pool and assigned based on transaction context. The context of the requesting thread and the assigned connection must match. Therefore, each connection pool is subdivided into connections with no associated transaction context and into *N* subdivisions that each contain connections with a particular transaction context.
|
||||
|
||||
When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. This allows you to commit or abort the distributed transaction at a later time.
|
||||
|
||||
### Control Connection Pooling with Connection String Keywords
|
||||
### Control connection pooling with connection string keywords
|
||||
|
||||
The <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A> property of the <xref:System.Data.OracleClient.OracleConnection> object supports connection string key/value pairs that can be used to adjust the behavior of the connection pooling logic.
|
||||
The <xref:System.Data.OracleClient.OracleConnection.ConnectionString> property of the <xref:System.Data.OracleClient.OracleConnection> object supports connection string key/value pairs that can be used to adjust the behavior of the connection pooling logic.
|
||||
|
||||
The following table describes the <xref:System.Data.OracleClient.OracleConnection.ConnectionString%2A> values you can use to adjust connection pooling behavior.
|
||||
The following table describes the <xref:System.Data.OracleClient.OracleConnection.ConnectionString> values you can use to adjust connection pooling behavior.
|
||||
|
||||
|Name|Default|Description|
|
||||
|----------|-------------|-----------------|
|
||||
| Name | Default | Description |
|
||||
|------|---------|-------------|
|
||||
|`Connection Lifetime`|0|When a connection is returned to the pool, its creation time is compared with the current time, and the connection is destroyed if that time span (in seconds) exceeds the value specified by `Connection Lifetime`. This is useful in clustered configurations to force load balancing between a running server and a server just brought online.<br /><br /> A value of zero (0) will cause pooled connections to have the maximum time-out.|
|
||||
|`Enlist`|'true'|When `true`, the pooler automatically enlists the connection in the current transaction context of the creation thread if a transaction context exists.|
|
||||
|`Max Pool Size`|100|The maximum number of connections allowed in the pool.|
|
||||
|
|
|
@ -1,100 +1,98 @@
|
|||
---
|
||||
description: "Learn more about: Oracle Sequences"
|
||||
description: "Learn more about retrieving the server-generated key Oracle Sequence values after performing inserts."
|
||||
title: "Oracle Sequences"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 27cd371d-8252-414d-b5b2-5d31fa44b585
|
||||
---
|
||||
# Oracle Sequences
|
||||
|
||||
The .NET Framework Data Provider for Oracle provides support for retrieving the server-generated key Oracle Sequence values after performing inserts by using the <xref:System.Data.OracleClient.OracleDataAdapter>.
|
||||
|
||||
SQL Server and Oracle support the creation of automatically incrementing columns that can be designated as primary keys. These values are generated by the server as rows are added to a table. In SQL Server, you set the Identity property of a column; in Oracle you create a Sequence. The difference between auto-increment columns in SQL Server and sequences in Oracle is that:
|
||||
|
||||
- In SQL Server, you mark a column as an auto-increment column and SQL Server automatically generates new values for the column when you insert a new row.
|
||||
|
||||
- In Oracle, you create a sequence to generate new values for a column in your table, but there is no direct link between the sequence and the table or column. An Oracle sequence is an object, like a table or a stored procedure.
|
||||
|
||||
When you create a sequence in an Oracle database, you can define its initial value and the increment between its values. You can also query the sequence for new values before submitting new rows. That means your code can recognize the key values for new rows before you insert them into the database.
|
||||
|
||||
For more information about creating auto-increment columns by using SQL Server and ADO.NET, see [Retrieving Identity or Autonumber Values](retrieving-identity-or-autonumber-values.md) and [Creating AutoIncrement Columns](./dataset-datatable-dataview/creating-autoincrement-columns.md).
|
||||
|
||||
## Example
|
||||
The .NET Framework Data Provider for Oracle provides support for retrieving the server-generated key Oracle Sequence values after performing inserts by using the <xref:System.Data.OracleClient.OracleDataAdapter>.
|
||||
|
||||
The following C# example demonstrates how you can retrieve new sequence values from Oracle database. The example references the sequence in the INSERT INTO query used to submit the new rows, and then returns the sequence value generated using the RETURNING clause introduced in Oracle10g. The example adds a series of pending new rows in a <xref:System.Data.DataTable> by using ADO.NET’s auto-increment functionality to generate "placeholder" primary key values. Note that the increment value ADO.NET generated for the new row is just a "placeholder". That means the database might generate different values from the ones ADO.NET generates.
|
||||
|
||||
Before submitting the pending inserts to the database, the example displays the contents of the rows. Then, the code creates a new <xref:System.Data.OracleClient.OracleDataAdapter> object and sets its <xref:System.Data.OracleClient.OracleDataAdapter.InsertCommand%2A> and the <xref:System.Data.OracleClient.OracleDataAdapter.UpdateBatchSize%2A> properties. The example also supplies the logic to return the server-generated values by using output parameters. Then, the example executes the update to submit the pending rows and displays the contents of the <xref:System.Data.DataTable>.
|
||||
|
||||
```csharp
|
||||
public void OracleSequence(String connectionString)
|
||||
{
|
||||
SQL Server and Oracle support the creation of automatically incrementing columns that can be designated as primary keys. These values are generated by the server as rows are added to a table. In SQL Server, you set the Identity property of a column; in Oracle you create a Sequence. The difference between auto-increment columns in SQL Server and sequences in Oracle is that:
|
||||
|
||||
- In SQL Server, you mark a column as an auto-increment column and SQL Server automatically generates new values for the column when you insert a new row.
|
||||
- In Oracle, you create a sequence to generate new values for a column in your table, but there is no direct link between the sequence and the table or column. An Oracle sequence is an object, like a table or a stored procedure.
|
||||
|
||||
When you create a sequence in an Oracle database, you can define its initial value and the increment between its values. You can also query the sequence for new values before submitting new rows. That means your code can recognize the key values for new rows before you insert them into the database.
|
||||
|
||||
For more information about creating auto-increment columns by using SQL Server and ADO.NET, see [Retrieving Identity or Autonumber Values](retrieving-identity-or-autonumber-values.md) and [Creating AutoIncrement Columns](./dataset-datatable-dataview/creating-autoincrement-columns.md).
|
||||
|
||||
## Example
|
||||
|
||||
The following C# example demonstrates how you can retrieve new sequence values from Oracle database. The example references the sequence in the `INSERT INTO` query used to submit the new rows, and then returns the sequence value generated using the `RETURNING` clause introduced in Oracle10g. The example adds a series of pending new rows in a <xref:System.Data.DataTable> by using ADO.NET's auto-increment functionality to generate "placeholder" primary key values. Note that the increment value ADO.NET generated for the new row is just a "placeholder". That means the database might generate different values from the ones ADO.NET generates.
|
||||
|
||||
Before submitting the pending inserts to the database, the example displays the contents of the rows. Then, the code creates a new <xref:System.Data.OracleClient.OracleDataAdapter> object and sets its <xref:System.Data.OracleClient.OracleDataAdapter.InsertCommand%2A> and the <xref:System.Data.OracleClient.OracleDataAdapter.UpdateBatchSize%2A> properties. The example also supplies the logic to return the server-generated values by using output parameters. Then, the example executes the update to submit the pending rows and displays the contents of the <xref:System.Data.DataTable>.
|
||||
|
||||
```csharp
|
||||
public void OracleSequence(String connectionString)
|
||||
{
|
||||
String insertString =
|
||||
"INSERT INTO SequenceTest_Table (ID, OtherColumn)" +
|
||||
"VALUES (SequenceTest_Sequence.NEXTVAL, :OtherColumn)" +
|
||||
"RETURNING ID INTO :ID";
|
||||
|
||||
using (OracleConnection conn = new OracleConnection(connectionString))
|
||||
{
|
||||
//Open a connection.
|
||||
conn.Open();
|
||||
OracleCommand cmd = conn.CreateCommand();
|
||||
|
||||
// Prepare the database.
|
||||
cmd.CommandText = "DROP SEQUENCE SequenceTest_Sequence";
|
||||
try { cmd.ExecuteNonQuery(); } catch { }
|
||||
|
||||
cmd.CommandText = "DROP TABLE SequenceTest_Table";
|
||||
try { cmd.ExecuteNonQuery(); } catch { }
|
||||
|
||||
cmd.CommandText = "CREATE TABLE SequenceTest_Table " +
|
||||
"(ID int PRIMARY KEY, OtherColumn varchar(255))";
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
cmd.CommandText = "CREATE SEQUENCE SequenceTest_Sequence " +
|
||||
"START WITH 100 INCREMENT BY 5";
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
DataTable testTable = new DataTable();
|
||||
DataColumn column = testTable.Columns.Add("ID", typeof(int));
|
||||
column.AutoIncrement = true;
|
||||
column.AutoIncrementSeed = -1;
|
||||
column.AutoIncrementStep = -1;
|
||||
testTable.PrimaryKey = new DataColumn[] { column };
|
||||
testTable.Columns.Add("OtherColumn", typeof(string));
|
||||
for (int rowCounter = 1; rowCounter <= 15; rowCounter++)
|
||||
{
|
||||
testTable.Rows.Add(null, "Row #" + rowCounter.ToString());
|
||||
}
|
||||
|
||||
Console.WriteLine("Before Update => ");
|
||||
foreach (DataRow row in testTable.Rows)
|
||||
{
|
||||
Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
"INSERT INTO SequenceTest_Table (ID, OtherColumn)" +
|
||||
"VALUES (SequenceTest_Sequence.NEXTVAL, :OtherColumn)" +
|
||||
"RETURNING ID INTO :ID";
|
||||
|
||||
using (OracleConnection conn = new OracleConnection(connectionString))
|
||||
{
|
||||
//Open a connection.
|
||||
conn.Open();
|
||||
OracleCommand cmd = conn.CreateCommand();
|
||||
|
||||
// Prepare the database.
|
||||
cmd.CommandText = "DROP SEQUENCE SequenceTest_Sequence";
|
||||
try { cmd.ExecuteNonQuery(); } catch { }
|
||||
|
||||
cmd.CommandText = "DROP TABLE SequenceTest_Table";
|
||||
try { cmd.ExecuteNonQuery(); } catch { }
|
||||
|
||||
cmd.CommandText = "CREATE TABLE SequenceTest_Table " +
|
||||
"(ID int PRIMARY KEY, OtherColumn varchar(255))";
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
cmd.CommandText = "CREATE SEQUENCE SequenceTest_Sequence " +
|
||||
"START WITH 100 INCREMENT BY 5";
|
||||
cmd.ExecuteNonQuery();
|
||||
|
||||
DataTable testTable = new DataTable();
|
||||
DataColumn column = testTable.Columns.Add("ID", typeof(int));
|
||||
column.AutoIncrement = true;
|
||||
column.AutoIncrementSeed = -1;
|
||||
column.AutoIncrementStep = -1;
|
||||
testTable.PrimaryKey = new DataColumn[] { column };
|
||||
testTable.Columns.Add("OtherColumn", typeof(string));
|
||||
for (int rowCounter = 1; rowCounter <= 15; rowCounter++)
|
||||
{
|
||||
testTable.Rows.Add(null, "Row #" + rowCounter.ToString());
|
||||
}
|
||||
|
||||
Console.WriteLine("Before Update => ");
|
||||
foreach (DataRow row in testTable.Rows)
|
||||
{
|
||||
Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
cmd.CommandText =
|
||||
"SELECT ID, OtherColumn FROM SequenceTest_Table";
|
||||
OracleDataAdapter da = new OracleDataAdapter(cmd);
|
||||
da.InsertCommand = new OracleCommand(insertString, conn);
|
||||
da.InsertCommand.Parameters.Add(":ID", OracleType.Int32, 0, "ID");
|
||||
da.InsertCommand.Parameters[0].Direction = ParameterDirection.Output;
|
||||
da.InsertCommand.Parameters.Add(":OtherColumn", OracleType.VarChar, 255, "OtherColumn");
|
||||
da.InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
|
||||
da.UpdateBatchSize = 10;
|
||||
|
||||
da.Update(testTable);
|
||||
|
||||
Console.WriteLine("After Update => ");
|
||||
foreach (DataRow row in testTable.Rows)
|
||||
{
|
||||
Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
|
||||
}
|
||||
// Close the connection.
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
"SELECT ID, OtherColumn FROM SequenceTest_Table";
|
||||
OracleDataAdapter da = new OracleDataAdapter(cmd);
|
||||
da.InsertCommand = new OracleCommand(insertString, conn);
|
||||
da.InsertCommand.Parameters.Add(":ID", OracleType.Int32, 0, "ID");
|
||||
da.InsertCommand.Parameters[0].Direction = ParameterDirection.Output;
|
||||
da.InsertCommand.Parameters.Add(":OtherColumn", OracleType.VarChar, 255, "OtherColumn");
|
||||
da.InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;
|
||||
da.UpdateBatchSize = 10;
|
||||
|
||||
da.Update(testTable);
|
||||
|
||||
Console.WriteLine("After Update => ");
|
||||
foreach (DataRow row in testTable.Rows)
|
||||
{
|
||||
Console.WriteLine(" {0} - {1}", row["ID"], row["OtherColumn"]);
|
||||
}
|
||||
// Close the connection.
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Oracle and ADO.NET](oracle-and-adonet.md)
|
||||
|
|
|
@ -1,118 +1,111 @@
|
|||
---
|
||||
description: "Learn more about: OracleTypes"
|
||||
description: "Learn more about the structures you can use to work with Oracle data types, including OracleNumber and OracleString."
|
||||
title: "OracleTypes"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 18143304-d5c7-4c95-9995-678088d0c142
|
||||
---
|
||||
# OracleTypes
|
||||
|
||||
The .NET Framework Data Provider for Oracle includes several structures you can use to work with Oracle data types. These include <xref:System.Data.OracleClient.OracleNumber> and <xref:System.Data.OracleClient.OracleString>.
|
||||
|
||||
The .NET Framework Data Provider for Oracle includes several structures you can use to work with Oracle data types. These include <xref:System.Data.OracleClient.OracleNumber> and <xref:System.Data.OracleClient.OracleString>.
|
||||
|
||||
> [!NOTE]
|
||||
> For a complete list of these structures, see <xref:System.Data.OracleClient>.
|
||||
|
||||
The following C# examples:
|
||||
|
||||
- Create an Oracle table and load it with data.
|
||||
|
||||
- Use an <xref:System.Data.OracleClient.OracleDataReader> to access the data, and use several <xref:System.Data.OracleClient.OracleType> structures to display the data.
|
||||
|
||||
## Creating an Oracle Table
|
||||
> For a complete list of these structures, see <xref:System.Data.OracleClient>.
|
||||
|
||||
This example creates an Oracle table and loads it with data. You must run this example before running the next example.
|
||||
|
||||
```csharp
|
||||
public void Setup(string connectionString)
|
||||
{
|
||||
OracleConnection conn = new OracleConnection(connectionString);
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
OracleCommand cmd = conn.CreateCommand();
|
||||
cmd.CommandText ="CREATE TABLE OracleTypesTable " +
|
||||
"(MyVarchar2 varchar2(3000),MyNumber number(28,4) " +
|
||||
"PRIMARY KEY ,MyDate date, MyRaw raw(255))";
|
||||
cmd.ExecuteNonQuery();
|
||||
cmd.CommandText ="INSERT INTO OracleTypesTable VALUES " +
|
||||
"( 'test', 2, to_date('2000-01-11 12:54:01','yyyy-mm-dd " +
|
||||
"hh24:mi:ss'), '0001020304' )";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Retrieving Data from the Oracle Table
|
||||
## Create an Oracle table
|
||||
|
||||
This example uses an **OracleDataReader** to access the data, and uses several **OracleType** structures to display the data.
|
||||
|
||||
```csharp
|
||||
public void ReadOracleTypesExample(string connectionString)
|
||||
{
|
||||
This example creates an Oracle table and loads it with data. You must run this example before running the next example.
|
||||
|
||||
```csharp
|
||||
public void Setup(string connectionString)
|
||||
{
|
||||
OracleConnection conn = new OracleConnection(connectionString);
|
||||
try
|
||||
{
|
||||
conn.Open();
|
||||
OracleCommand cmd = conn.CreateCommand();
|
||||
cmd.CommandText ="CREATE TABLE OracleTypesTable " +
|
||||
"(MyVarchar2 varchar2(3000),MyNumber number(28,4) " +
|
||||
"PRIMARY KEY ,MyDate date, MyRaw raw(255))";
|
||||
cmd.ExecuteNonQuery();
|
||||
cmd.CommandText ="INSERT INTO OracleTypesTable VALUES " +
|
||||
"( 'test', 2, to_date('2000-01-11 12:54:01','yyyy-mm-dd " +
|
||||
"hh24:mi:ss'), '0001020304' )";
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Retrieve data from the Oracle table
|
||||
|
||||
This example uses an **OracleDataReader** to access the data, and uses several **OracleType** structures to display the data.
|
||||
|
||||
```csharp
|
||||
public void ReadOracleTypesExample(string connectionString)
|
||||
{
|
||||
OracleConnection myConnection =
|
||||
new OracleConnection(connectionString);
|
||||
myConnection.Open();
|
||||
OracleCommand myCommand = myConnection.CreateCommand();
|
||||
|
||||
try
|
||||
{
|
||||
myCommand.CommandText = "SELECT * from OracleTypesTable";
|
||||
OracleDataReader oracledatareader1 = myCommand.ExecuteReader();
|
||||
oracledatareader1.Read();
|
||||
|
||||
//Using the oracle specific getters for each type is faster than
|
||||
//using GetOracleValue.
|
||||
|
||||
//First column, MyVarchar2, is a VARCHAR2 data type in Oracle
|
||||
//Server and maps to OracleString.
|
||||
new OracleConnection(connectionString);
|
||||
myConnection.Open();
|
||||
OracleCommand myCommand = myConnection.CreateCommand();
|
||||
|
||||
try
|
||||
{
|
||||
myCommand.CommandText = "SELECT * from OracleTypesTable";
|
||||
OracleDataReader oracledatareader1 = myCommand.ExecuteReader();
|
||||
oracledatareader1.Read();
|
||||
|
||||
//Using the oracle specific getters for each type is faster than
|
||||
//using GetOracleValue.
|
||||
|
||||
//First column, MyVarchar2, is a VARCHAR2 data type in Oracle
|
||||
//Server and maps to OracleString.
|
||||
OracleString oraclestring1 =
|
||||
oracledatareader1.GetOracleString(0);
|
||||
Console.WriteLine("OracleString " + oraclestring1.ToString());
|
||||
|
||||
//Second column, MyNumber, is a NUMBER data type in Oracle Server
|
||||
//and maps to OracleNumber.
|
||||
oracledatareader1.GetOracleString(0);
|
||||
Console.WriteLine("OracleString " + oraclestring1.ToString());
|
||||
|
||||
//Second column, MyNumber, is a NUMBER data type in Oracle Server
|
||||
//and maps to OracleNumber.
|
||||
OracleNumber oraclenumber1 =
|
||||
oracledatareader1.GetOracleNumber(1);
|
||||
Console.WriteLine("OracleNumber " + oraclenumber1.ToString());
|
||||
|
||||
//Third column, MyDate, is a DATA data type in Oracle Server
|
||||
//and maps to OracleDateTime.
|
||||
oracledatareader1.GetOracleNumber(1);
|
||||
Console.WriteLine("OracleNumber " + oraclenumber1.ToString());
|
||||
|
||||
//Third column, MyDate, is a DATA data type in Oracle Server
|
||||
//and maps to OracleDateTime.
|
||||
OracleDateTime oracledatetime1 =
|
||||
oracledatareader1.GetOracleDateTime(2);
|
||||
Console.WriteLine("OracleDateTime " + oracledatetime1.ToString());
|
||||
|
||||
//Fourth column, MyRaw, is a RAW data type in Oracle Server and
|
||||
//maps to OracleBinary.
|
||||
oracledatareader1.GetOracleDateTime(2);
|
||||
Console.WriteLine("OracleDateTime " + oracledatetime1.ToString());
|
||||
|
||||
//Fourth column, MyRaw, is a RAW data type in Oracle Server and
|
||||
//maps to OracleBinary.
|
||||
OracleBinary oraclebinary1 =
|
||||
oracledatareader1.GetOracleBinary(3);
|
||||
//Calling value on a null OracleBinary throws
|
||||
//OracleNullValueException; therefore, check for a null value.
|
||||
if (oraclebinary1.IsNull==false)
|
||||
{
|
||||
foreach(byte b in oraclebinary1.Value)
|
||||
{
|
||||
Console.WriteLine("byte " + b.ToString());
|
||||
}
|
||||
}
|
||||
oracledatareader1.Close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
myConnection.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
oracledatareader1.GetOracleBinary(3);
|
||||
//Calling value on a null OracleBinary throws
|
||||
//OracleNullValueException; therefore, check for a null value.
|
||||
if (oraclebinary1.IsNull==false)
|
||||
{
|
||||
foreach(byte b in oraclebinary1.Value)
|
||||
{
|
||||
Console.WriteLine("byte " + b.ToString());
|
||||
}
|
||||
}
|
||||
oracledatareader1.Close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
myConnection.Close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Oracle and ADO.NET](oracle-and-adonet.md)
|
||||
|
|
|
@ -5,9 +5,8 @@ ms.date: "03/30/2017"
|
|||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 0b121b71-78f8-4ae2-9aa1-0b2e15778e57
|
||||
---
|
||||
# Performance Counters in ADO.NET
|
||||
# Performance counters in ADO.NET
|
||||
|
||||
ADO.NET 2.0 introduced expanded support for performance counters that includes support for both <xref:System.Data.SqlClient> and <xref:System.Data.OracleClient>. The <xref:System.Data.SqlClient> performance counters available in previous versions of ADO.NET have been deprecated and replaced with the new performance counters discussed in this topic. You can use ADO.NET performance counters to monitor the status of your application and the connection resources that it uses. Performance counters can be monitored by using Windows Performance Monitor or can be accessed programmatically using the <xref:System.Diagnostics.PerformanceCounter> class in the <xref:System.Diagnostics> namespace.
|
||||
|
||||
|
@ -15,28 +14,28 @@ ADO.NET 2.0 introduced expanded support for performance counters that includes s
|
|||
|
||||
Currently there are 14 different performance counters available for <xref:System.Data.SqlClient> and <xref:System.Data.OracleClient> as described in the following table. Note that the names for the individual counters are not localized across regional versions of the Microsoft .NET Framework.
|
||||
|
||||
|Performance counter|Description|
|
||||
|-------------------------|-----------------|
|
||||
|`HardConnectsPerSecond`|The number of connections per second that are being made to a database server.|
|
||||
|`HardDisconnectsPerSecond`|The number of disconnects per second that are being made to a database server.|
|
||||
| Performance counter | Description |
|
||||
|----------------------------|--------------------------------------------------------------------------------|
|
||||
| `HardConnectsPerSecond` | The number of connections per second that are being made to a database server. |
|
||||
| `HardDisconnectsPerSecond` | The number of disconnects per second that are being made to a database server. |
|
||||
|`NumberOfActiveConnectionPoolGroups`|The number of unique connection pool groups that are active. This counter is controlled by the number of unique connection strings that are found in the AppDomain.|
|
||||
|`NumberOfActiveConnectionPools`|The total number of connection pools.|
|
||||
|`NumberOfActiveConnections`|The number of active connections that are currently in use. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#ActivatingOffByDefault).|
|
||||
|`NumberOfFreeConnections`|The number of connections available for use in the connection pools. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#ActivatingOffByDefault).|
|
||||
|`NumberOfActiveConnections`|The number of active connections that are currently in use. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#activating-off-by-default-counters).|
|
||||
|`NumberOfFreeConnections`|The number of connections available for use in the connection pools. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#activating-off-by-default-counters).|
|
||||
|`NumberOfInactiveConnectionPoolGroups`|The number of unique connection pool groups that are marked for pruning. This counter is controlled by the number of unique connection strings that are found in the AppDomain.|
|
||||
|`NumberOfInactiveConnectionPools`|The number of inactive connection pools that have not had any recent activity and are waiting to be disposed.|
|
||||
|`NumberOfNonPooledConnections`|The number of active connections that are not pooled.|
|
||||
|`NumberOfPooledConnections`|The number of active connections that are being managed by the connection pooling infrastructure.|
|
||||
|`NumberOfReclaimedConnections`|The number of connections that have been reclaimed through garbage collection where `Close` or `Dispose` was not called by the application. Not explicitly closing or disposing connections hurts performance.|
|
||||
|`NumberOfStasisConnections`|The number of connections currently awaiting completion of an action and which are therefore unavailable for use by your application.|
|
||||
|`SoftConnectsPerSecond`|The number of active connections being pulled from the connection pool. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#ActivatingOffByDefault).|
|
||||
|`SoftDisconnectsPerSecond`|The number of active connections that are being returned to the connection pool. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#ActivatingOffByDefault).|
|
||||
|`SoftConnectsPerSecond`|The number of active connections being pulled from the connection pool. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#activating-off-by-default-counters).|
|
||||
|`SoftDisconnectsPerSecond`|The number of active connections that are being returned to the connection pool. **Note:** This performance counter is not enabled by default. To enable this performance counter, see [Activating Off-By-Default Counters](#activating-off-by-default-counters).|
|
||||
|
||||
### Connection Pool Groups and Connection Pools
|
||||
|
||||
When using Windows Authentication (integrated security), you must monitor both the `NumberOfActiveConnectionPoolGroups` and `NumberOfActiveConnectionPools` performance counters. The reason is that connection pool groups map to unique connection strings. When integrated security is used, connection pools map to connection strings and additionally create separate pools for individual Windows identities. For example, if Fred and Julie, each within the same AppDomain, both use the connection string `"Data Source=MySqlServer;Integrated Security=true"`, a connection pool group is created for the connection string, and two additional pools are created, one for Fred and one for Julie. If John and Martha use a connection string with an identical SQL Server login, `"Data Source=MySqlServer;User Id=lowPrivUser;Password=[PLACEHOLDER]"`, then only a single pool is created for the **lowPrivUser** identity.
|
||||
When using Windows Authentication (integrated security), you must monitor both the `NumberOfActiveConnectionPoolGroups` and `NumberOfActiveConnectionPools` performance counters. The reason is that connection pool groups map to unique connection strings. When integrated security is used, connection pools map to connection strings and additionally create separate pools for individual Windows identities. For example, if Fred and Julie, each within the same AppDomain, both use the connection string `"Data Source=MySqlServer;Integrated Security=true"`, a connection pool group is created for the connection string, and two additional pools are created, one for Fred and one for Julie. If John and Martha use a connection string with an identical SQL Server login, `"Data Source=MySqlServer;User Id=lowPrivUser;Password=[PLACEHOLDER]"`, then only a single pool is created for the **lowPrivUser** identity.
|
||||
|
||||
<a name="ActivatingOffByDefault"></a>
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
### Activating Off-By-Default Counters
|
||||
|
||||
|
@ -200,27 +199,6 @@ Class Program
|
|||
Next
|
||||
Console.WriteLine("---------------------------")
|
||||
End Sub
|
||||
|
||||
Private Shared Function GetIntegratedSecurityConnectionString() As String
|
||||
' To avoid storing the connection string in your code,
|
||||
' you can retrieve it from a configuration file.
|
||||
Return ("Data Source=.\SqlExpress;Integrated Security=True;" &
|
||||
"Initial Catalog=AdventureWorks")
|
||||
End Function
|
||||
|
||||
Private Shared Function GetSqlConnectionString() As String
|
||||
' To avoid storing the connection string in your code,
|
||||
' you can retrieve it from a configuration file.
|
||||
Return ("Data Source=.\SqlExpress;User Id=LowPriv;Password=[PLACEHOLDER];" &
|
||||
"Initial Catalog=AdventureWorks")
|
||||
End Function
|
||||
|
||||
Private Shared Function GetSqlConnectionStringDifferent() As String
|
||||
' To avoid storing the connection string in your code,
|
||||
' you can retrieve it from a configuration file.
|
||||
Return ("Initial Catalog=AdventureWorks;Data Source=.\SqlExpress;" & _
|
||||
"User Id=LowPriv;Password=[PLACEHOLDER];")
|
||||
End Function
|
||||
End Class
|
||||
```
|
||||
|
||||
|
@ -369,29 +347,6 @@ class Program
|
|||
}
|
||||
Console.WriteLine("---------------------------");
|
||||
}
|
||||
|
||||
private static string GetIntegratedSecurityConnectionString()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return @"Data Source=.\SqlExpress;Integrated Security=True;" +
|
||||
"Initial Catalog=AdventureWorks";
|
||||
}
|
||||
private static string GetSqlConnectionString()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return @"Data Source=.\SqlExpress;User Id=LowPriv;Password=[PLACEHOLDER];" +
|
||||
"Initial Catalog=AdventureWorks";
|
||||
}
|
||||
|
||||
private static string GetSqlConnectionStringDifferent()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return @"Initial Catalog=AdventureWorks;Data Source=.\SqlExpress;" +
|
||||
"User Id=LowPriv;Password=[PLACEHOLDER];";
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -1,147 +1,146 @@
|
|||
---
|
||||
description: "Learn more about: Performing Batch Operations Using DataAdapters"
|
||||
description: "Learn more about batching operations using DataAdapters, instead of sending one operation at a time, to improve performance."
|
||||
title: "Performing Batch Operations Using DataAdapters"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: e72ed5af-b24f-486c-8429-c8fd2208f844
|
||||
---
|
||||
# Performing Batch Operations Using DataAdapters
|
||||
# Perform batch operations using DataAdapters
|
||||
|
||||
Batch support in ADO.NET allows a <xref:System.Data.Common.DataAdapter> to group INSERT, UPDATE, and DELETE operations from a <xref:System.Data.DataSet> or <xref:System.Data.DataTable> to the server, instead of sending one operation at a time. The reduction in the number of round trips to the server typically results in significant performance gains. Batch updates are supported for the .NET data providers for SQL Server (<xref:System.Data.SqlClient>) and Oracle (<xref:System.Data.OracleClient>).
|
||||
|
||||
When updating a database with changes from a <xref:System.Data.DataSet> in previous versions of ADO.NET, the `Update` method of a `DataAdapter` performed updates to the database one row at a time. As it iterated through the rows in the specified <xref:System.Data.DataTable>, it examined each <xref:System.Data.DataRow> to see if it had been modified. If the row had been modified, it called the appropriate `UpdateCommand`, `InsertCommand`, or `DeleteCommand`, depending on the value of the <xref:System.Data.DataRow.RowState%2A> property for that row. Every row update involved a network round-trip to the database.
|
||||
|
||||
Starting with ADO.NET 2.0, the <xref:System.Data.Common.DbDataAdapter> exposes an <xref:System.Data.Common.DbDataAdapter.UpdateBatchSize%2A> property. Setting the `UpdateBatchSize` to a positive integer value causes updates to the database to be sent as batches of the specified size. For example, setting the `UpdateBatchSize` to 10 will group 10 separate statements and submit them as single batch. Setting the `UpdateBatchSize` to 0 will cause the <xref:System.Data.Common.DataAdapter> to use the largest batch size that the server can handle. Setting it to 1 disables batch updates, as rows are sent one at a time.
|
||||
|
||||
Executing an extremely large batch could decrease performance. Therefore, you should test for the optimum batch size setting before implementing your application.
|
||||
|
||||
## Using the UpdateBatchSize Property
|
||||
Batch support in ADO.NET allows a <xref:System.Data.Common.DataAdapter> to group INSERT, UPDATE, and DELETE operations from a <xref:System.Data.DataSet> or <xref:System.Data.DataTable> to the server, instead of sending one operation at a time. The reduction in the number of round trips to the server typically results in significant performance gains. Batch updates are supported for the .NET data providers for SQL Server (<xref:System.Data.SqlClient>) and Oracle (<xref:System.Data.OracleClient>).
|
||||
|
||||
When batch updates are enabled, the <xref:System.Data.IDbCommand.UpdatedRowSource%2A> property value of the DataAdapter's `UpdateCommand`, `InsertCommand`, and `DeleteCommand` should be set to <xref:System.Data.UpdateRowSource.None> or <xref:System.Data.UpdateRowSource.OutputParameters>. When performing a batch update, the command's <xref:System.Data.IDbCommand.UpdatedRowSource%2A> property value of <xref:System.Data.UpdateRowSource.FirstReturnedRecord> or <xref:System.Data.UpdateRowSource.Both> is invalid.
|
||||
|
||||
The following procedure demonstrates the use of the `UpdateBatchSize` property. The procedure takes two arguments, a <xref:System.Data.DataSet> object that has columns representing the **ProductCategoryID** and **Name** fields in the **Production.ProductCategory** table, and an integer representing the batch size (the number of rows in the batch). The code creates a new <xref:System.Data.SqlClient.SqlDataAdapter> object, setting its <xref:System.Data.SqlClient.SqlDataAdapter.UpdateCommand%2A>, <xref:System.Data.SqlClient.SqlDataAdapter.InsertCommand%2A>, and <xref:System.Data.SqlClient.SqlDataAdapter.DeleteCommand%2A> properties. The code assumes that the <xref:System.Data.DataSet> object has modified rows. It sets the `UpdateBatchSize` property and executes the update.
|
||||
|
||||
```vb
|
||||
Public Sub BatchUpdate( _
|
||||
ByVal dataTable As DataTable, ByVal batchSize As Int32)
|
||||
' Assumes GetConnectionString() returns a valid connection string.
|
||||
Dim connectionString As String = GetConnectionString()
|
||||
|
||||
' Connect to the AdventureWorks database.
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
' Create a SqlDataAdapter.
|
||||
Dim adapter As New SqlDataAdapter()
|
||||
|
||||
'Set the UPDATE command and parameters.
|
||||
adapter.UpdateCommand = New SqlCommand( _
|
||||
"UPDATE Production.ProductCategory SET " _
|
||||
& "Name=@Name WHERE ProductCategoryID=@ProdCatID;", _
|
||||
connection)
|
||||
adapter.UpdateCommand.Parameters.Add("@Name", _
|
||||
SqlDbType.NVarChar, 50, "Name")
|
||||
adapter.UpdateCommand.Parameters.Add("@ProdCatID", _
|
||||
SqlDbType.Int, 4, " ProductCategoryID ")
|
||||
adapter.UpdateCommand.UpdatedRowSource = _
|
||||
UpdateRowSource.None
|
||||
|
||||
'Set the INSERT command and parameter.
|
||||
adapter.InsertCommand = New SqlCommand( _
|
||||
"INSERT INTO Production.ProductCategory (Name) VALUES (@Name);", _
|
||||
connection)
|
||||
adapter.InsertCommand.Parameters.Add("@Name", _
|
||||
SqlDbType.NVarChar, 50, "Name")
|
||||
adapter.InsertCommand.UpdatedRowSource = _
|
||||
UpdateRowSource.None
|
||||
|
||||
'Set the DELETE command and parameter.
|
||||
adapter.DeleteCommand = New SqlCommand( _
|
||||
"DELETE FROM Production.ProductCategory " _
|
||||
& "WHERE ProductCategoryID=@ProdCatID;", connection)
|
||||
adapter.DeleteCommand.Parameters.Add("@ProdCatID", _
|
||||
SqlDbType.Int, 4, " ProductCategoryID ")
|
||||
adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None
|
||||
|
||||
' Set the batch size.
|
||||
adapter.UpdateBatchSize = batchSize
|
||||
|
||||
' Execute the update.
|
||||
adapter.Update(dataTable)
|
||||
End Using
|
||||
End Sub
|
||||
```
|
||||
|
||||
```csharp
|
||||
public static void BatchUpdate(DataTable dataTable,Int32 batchSize)
|
||||
{
|
||||
// Assumes GetConnectionString() returns a valid connection string.
|
||||
string connectionString = GetConnectionString();
|
||||
|
||||
// Connect to the AdventureWorks database.
|
||||
When updating a database with changes from a <xref:System.Data.DataSet> in previous versions of ADO.NET, the `Update` method of a `DataAdapter` performed updates to the database one row at a time. As it iterated through the rows in the specified <xref:System.Data.DataTable>, it examined each <xref:System.Data.DataRow> to see if it had been modified. If the row had been modified, it called the appropriate `UpdateCommand`, `InsertCommand`, or `DeleteCommand`, depending on the value of the <xref:System.Data.DataRow.RowState%2A> property for that row. Every row update involved a network round-trip to the database.
|
||||
|
||||
Starting with ADO.NET 2.0, the <xref:System.Data.Common.DbDataAdapter> exposes an <xref:System.Data.Common.DbDataAdapter.UpdateBatchSize%2A> property. Setting the `UpdateBatchSize` to a positive integer value causes updates to the database to be sent as batches of the specified size. For example, setting the `UpdateBatchSize` to 10 will group 10 separate statements and submit them as single batch. Setting the `UpdateBatchSize` to 0 will cause the <xref:System.Data.Common.DataAdapter> to use the largest batch size that the server can handle. Setting it to 1 disables batch updates, as rows are sent one at a time.
|
||||
|
||||
Executing an extremely large batch could decrease performance. Therefore, you should test for the optimum batch size setting before implementing your application.
|
||||
|
||||
## Using the UpdateBatchSize Property
|
||||
|
||||
When batch updates are enabled, the <xref:System.Data.IDbCommand.UpdatedRowSource%2A> property value of the DataAdapter's `UpdateCommand`, `InsertCommand`, and `DeleteCommand` should be set to <xref:System.Data.UpdateRowSource.None> or <xref:System.Data.UpdateRowSource.OutputParameters>. When performing a batch update, the command's <xref:System.Data.IDbCommand.UpdatedRowSource%2A> property value of <xref:System.Data.UpdateRowSource.FirstReturnedRecord> or <xref:System.Data.UpdateRowSource.Both> is invalid.
|
||||
|
||||
The following procedure demonstrates the use of the `UpdateBatchSize` property. The procedure takes two arguments, a <xref:System.Data.DataSet> object that has columns representing the **ProductCategoryID** and **Name** fields in the **Production.ProductCategory** table, and an integer representing the batch size (the number of rows in the batch). The code creates a new <xref:System.Data.SqlClient.SqlDataAdapter> object, setting its <xref:System.Data.SqlClient.SqlDataAdapter.UpdateCommand%2A>, <xref:System.Data.SqlClient.SqlDataAdapter.InsertCommand%2A>, and <xref:System.Data.SqlClient.SqlDataAdapter.DeleteCommand%2A> properties. The code assumes that the <xref:System.Data.DataSet> object has modified rows. It sets the `UpdateBatchSize` property and executes the update.
|
||||
|
||||
```vb
|
||||
Public Sub BatchUpdate( _
|
||||
ByVal dataTable As DataTable, ByVal batchSize As Int32)
|
||||
' Assumes GetConnectionString() returns a valid connection string.
|
||||
Dim connectionString As String = GetConnectionString()
|
||||
|
||||
' Connect to the AdventureWorks database.
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
' Create a SqlDataAdapter.
|
||||
Dim adapter As New SqlDataAdapter()
|
||||
|
||||
'Set the UPDATE command and parameters.
|
||||
adapter.UpdateCommand = New SqlCommand( _
|
||||
"UPDATE Production.ProductCategory SET " _
|
||||
& "Name=@Name WHERE ProductCategoryID=@ProdCatID;", _
|
||||
connection)
|
||||
adapter.UpdateCommand.Parameters.Add("@Name", _
|
||||
SqlDbType.NVarChar, 50, "Name")
|
||||
adapter.UpdateCommand.Parameters.Add("@ProdCatID", _
|
||||
SqlDbType.Int, 4, " ProductCategoryID ")
|
||||
adapter.UpdateCommand.UpdatedRowSource = _
|
||||
UpdateRowSource.None
|
||||
|
||||
'Set the INSERT command and parameter.
|
||||
adapter.InsertCommand = New SqlCommand( _
|
||||
"INSERT INTO Production.ProductCategory (Name) VALUES (@Name);", _
|
||||
connection)
|
||||
adapter.InsertCommand.Parameters.Add("@Name", _
|
||||
SqlDbType.NVarChar, 50, "Name")
|
||||
adapter.InsertCommand.UpdatedRowSource = _
|
||||
UpdateRowSource.None
|
||||
|
||||
'Set the DELETE command and parameter.
|
||||
adapter.DeleteCommand = New SqlCommand( _
|
||||
"DELETE FROM Production.ProductCategory " _
|
||||
& "WHERE ProductCategoryID=@ProdCatID;", connection)
|
||||
adapter.DeleteCommand.Parameters.Add("@ProdCatID", _
|
||||
SqlDbType.Int, 4, " ProductCategoryID ")
|
||||
adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None
|
||||
|
||||
' Set the batch size.
|
||||
adapter.UpdateBatchSize = batchSize
|
||||
|
||||
' Execute the update.
|
||||
adapter.Update(dataTable)
|
||||
End Using
|
||||
End Sub
|
||||
```
|
||||
|
||||
```csharp
|
||||
public static void BatchUpdate(DataTable dataTable,Int32 batchSize)
|
||||
{
|
||||
// Assumes GetConnectionString() returns a valid connection string.
|
||||
string connectionString = GetConnectionString();
|
||||
|
||||
// Connect to the AdventureWorks database.
|
||||
using (SqlConnection connection = new
|
||||
SqlConnection(connectionString))
|
||||
{
|
||||
|
||||
// Create a SqlDataAdapter.
|
||||
SqlDataAdapter adapter = new SqlDataAdapter();
|
||||
|
||||
// Set the UPDATE command and parameters.
|
||||
adapter.UpdateCommand = new SqlCommand(
|
||||
"UPDATE Production.ProductCategory SET "
|
||||
SqlConnection(connectionString))
|
||||
{
|
||||
|
||||
// Create a SqlDataAdapter.
|
||||
SqlDataAdapter adapter = new SqlDataAdapter();
|
||||
|
||||
// Set the UPDATE command and parameters.
|
||||
adapter.UpdateCommand = new SqlCommand(
|
||||
"UPDATE Production.ProductCategory SET "
|
||||
+ "Name=@Name WHERE ProductCategoryID=@ProdCatID;",
|
||||
connection);
|
||||
connection);
|
||||
adapter.UpdateCommand.Parameters.Add("@Name",
|
||||
SqlDbType.NVarChar, 50, "Name");
|
||||
SqlDbType.NVarChar, 50, "Name");
|
||||
adapter.UpdateCommand.Parameters.Add("@ProdCatID",
|
||||
SqlDbType.Int, 4, "ProductCategoryID");
|
||||
adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
// Set the INSERT command and parameter.
|
||||
adapter.InsertCommand = new SqlCommand(
|
||||
SqlDbType.Int, 4, "ProductCategoryID");
|
||||
adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
// Set the INSERT command and parameter.
|
||||
adapter.InsertCommand = new SqlCommand(
|
||||
"INSERT INTO Production.ProductCategory (Name) VALUES (@Name);",
|
||||
connection);
|
||||
connection);
|
||||
adapter.InsertCommand.Parameters.Add("@Name",
|
||||
SqlDbType.NVarChar, 50, "Name");
|
||||
adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
// Set the DELETE command and parameter.
|
||||
adapter.DeleteCommand = new SqlCommand(
|
||||
"DELETE FROM Production.ProductCategory "
|
||||
+ "WHERE ProductCategoryID=@ProdCatID;", connection);
|
||||
SqlDbType.NVarChar, 50, "Name");
|
||||
adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
// Set the DELETE command and parameter.
|
||||
adapter.DeleteCommand = new SqlCommand(
|
||||
"DELETE FROM Production.ProductCategory "
|
||||
+ "WHERE ProductCategoryID=@ProdCatID;", connection);
|
||||
adapter.DeleteCommand.Parameters.Add("@ProdCatID",
|
||||
SqlDbType.Int, 4, "ProductCategoryID");
|
||||
adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
// Set the batch size.
|
||||
adapter.UpdateBatchSize = batchSize;
|
||||
|
||||
// Execute the update.
|
||||
adapter.Update(dataTable);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Handling Batch Update-Related Events and Errors
|
||||
SqlDbType.Int, 4, "ProductCategoryID");
|
||||
adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None;
|
||||
|
||||
The **DataAdapter** has two update-related events: **RowUpdating** and **RowUpdated**. In previous versions of ADO.NET, when batch processing is disabled, each of these events is generated once for each row processed. **RowUpdating** is generated before the update occurs, and **RowUpdated** is generated after the database update has been completed.
|
||||
|
||||
### Event Behavior Changes with Batch Updates
|
||||
// Set the batch size.
|
||||
adapter.UpdateBatchSize = batchSize;
|
||||
|
||||
When batch processing is enabled, multiple rows are updated in a single database operation. Therefore, only one `RowUpdated` event occurs for each batch, whereas the `RowUpdating` event occurs for each row processed. When batch processing is disabled, the two events are fired with one-to-one interleaving, where one `RowUpdating` event and one `RowUpdated` event fire for a row, and then one `RowUpdating` and one `RowUpdated` event fire for the next row, until all of the rows are processed.
|
||||
|
||||
### Accessing Updated Rows
|
||||
// Execute the update.
|
||||
adapter.Update(dataTable);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When batch processing is disabled, the row being updated can be accessed using the <xref:System.Data.Common.RowUpdatedEventArgs.Row%2A> property of the <xref:System.Data.Common.RowUpdatedEventArgs> class.
|
||||
|
||||
When batch processing is enabled, a single `RowUpdated` event is generated for multiple rows. Therefore, the value of the `Row` property for each row is null. `RowUpdating` events are still generated for each row. The <xref:System.Data.Common.RowUpdatedEventArgs.CopyToRows%2A> method of the <xref:System.Data.Common.RowUpdatedEventArgs> class allows you to access the processed rows by copying references to the rows into an array. If no rows are being processed, `CopyToRows` throws an <xref:System.ArgumentNullException>. Use the <xref:System.Data.Common.RowUpdatedEventArgs.RowCount%2A> property to return the number of rows processed before calling the <xref:System.Data.Common.RowUpdatedEventArgs.CopyToRows%2A> method.
|
||||
|
||||
### Handling Data Errors
|
||||
## Handling Batch Update-Related Events and Errors
|
||||
|
||||
The **DataAdapter** has two update-related events: **RowUpdating** and **RowUpdated**. In previous versions of ADO.NET, when batch processing is disabled, each of these events is generated once for each row processed. **RowUpdating** is generated before the update occurs, and **RowUpdated** is generated after the database update has been completed.
|
||||
|
||||
### Event Behavior Changes with Batch Updates
|
||||
|
||||
When batch processing is enabled, multiple rows are updated in a single database operation. Therefore, only one `RowUpdated` event occurs for each batch, whereas the `RowUpdating` event occurs for each row processed. When batch processing is disabled, the two events are fired with one-to-one interleaving, where one `RowUpdating` event and one `RowUpdated` event fire for a row, and then one `RowUpdating` and one `RowUpdated` event fire for the next row, until all of the rows are processed.
|
||||
|
||||
### Accessing Updated Rows
|
||||
|
||||
When batch processing is disabled, the row being updated can be accessed using the <xref:System.Data.Common.RowUpdatedEventArgs.Row%2A> property of the <xref:System.Data.Common.RowUpdatedEventArgs> class.
|
||||
|
||||
When batch processing is enabled, a single `RowUpdated` event is generated for multiple rows. Therefore, the value of the `Row` property for each row is null. `RowUpdating` events are still generated for each row. The <xref:System.Data.Common.RowUpdatedEventArgs.CopyToRows%2A> method of the <xref:System.Data.Common.RowUpdatedEventArgs> class allows you to access the processed rows by copying references to the rows into an array. If no rows are being processed, `CopyToRows` throws an <xref:System.ArgumentNullException>. Use the <xref:System.Data.Common.RowUpdatedEventArgs.RowCount%2A> property to return the number of rows processed before calling the <xref:System.Data.Common.RowUpdatedEventArgs.CopyToRows%2A> method.
|
||||
|
||||
### Handling Data Errors
|
||||
|
||||
Batch execution has the same effect as the execution of each individual statement. Statements are executed in the order that the statements were added to the batch. Errors are handled the same way in batch mode as they are when batch mode is disabled. Each row is processed separately. Only rows that have been successfully processed in the database will be updated in the corresponding <xref:System.Data.DataRow> within the <xref:System.Data.DataTable>.
|
||||
|
||||
The data provider and the back-end database server determine which SQL constructs are supported for batch execution. An exception may be thrown if a non-supported statement is submitted for execution.
|
||||
|
||||
Batch execution has the same effect as the execution of each individual statement. Statements are executed in the order that the statements were added to the batch. Errors are handled the same way in batch mode as they are when batch mode is disabled. Each row is processed separately. Only rows that have been successfully processed in the database will be updated in the corresponding <xref:System.Data.DataRow> within the <xref:System.Data.DataTable>.
|
||||
|
||||
The data provider and the back-end database server determine which SQL constructs are supported for batch execution. An exception may be thrown if a non-supported statement is submitted for execution.
|
||||
|
||||
## See also
|
||||
|
||||
- [DataAdapters and DataReaders](dataadapters-and-datareaders.md)
|
||||
|
|
|
@ -2,19 +2,20 @@
|
|||
title: "Protecting Connection Information"
|
||||
description: Learn about security vulnerabilities in connection strings, which can arise due to how connection strings are constructed and persisted and authentication type.
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 1471f580-bcd4-4046-bdaf-d2541ecda2f4
|
||||
---
|
||||
# Protecting Connection Information
|
||||
# Protect connection information
|
||||
|
||||
Protecting access to your data source is one of the most important goals when securing an application. A connection string presents a potential vulnerability if it is not secured. Storing connection information in plain text or persisting it in memory risks compromising your entire system. Connection strings embedded in your source code can be read using the [Ildasm.exe (IL Disassembler)](../../tools/ildasm-exe-il-disassembler.md) to view common intermediate language (CIL) in a compiled assembly.
|
||||
Protecting access to your data source is one of the most important goals when securing an application. A connection string presents a potential vulnerability if it isn't secured. Storing connection information in plain text or persisting it in memory risks compromising your entire system. Connection strings embedded in your source code can be read using the [Ildasm.exe (IL Disassembler)](../../tools/ildasm-exe-il-disassembler.md) to view common intermediate language (CIL) in a compiled assembly.
|
||||
|
||||
Security vulnerabilities involving connection strings can arise based on the type of authentication used, how connection strings are persisted in memory and on disk, and the techniques used to construct them at run time.
|
||||
Security vulnerabilities involving connection strings can arise based on the type of authentication used, how connection strings are persisted in memory and on disk, and the techniques used to construct them at run time.
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
## Use Windows Authentication
|
||||
|
||||
To help limit access to your data source, you must secure connection information such as user ID, password, and data source name. In order to avoid exposing user information, we recommend using Windows authentication (sometimes referred to as *integrated security*) wherever possible. Windows authentication is specified in a connection string by using the `Integrated Security` or `Trusted_Connection` keywords, eliminating the need to use a user ID and password. When using Windows authentication, users are authenticated by Windows, and access to server and database resources is determined by granting permissions to Windows users and groups.
|
||||
To help limit access to your data source, you must secure connection information such as user ID, password, and data source name. To avoid exposing user information, we recommend using Windows authentication (sometimes referred to as *integrated security*) for on-premises data sources. (However, when connecting to Azure SQL, you should use [Managed Identities for Azure resources](/sql/connect/ado-net/sql/azure-active-directory-authentication#using-managed-identity-authentication).) Windows authentication is specified in a connection string by using the `Integrated Security` or `Trusted_Connection` keywords, eliminating the need to use a user ID and password. When using Windows authentication, users are authenticated by Windows, and access to server and database resources is determined by granting permissions to Windows users and groups.
|
||||
|
||||
For situations where it is not possible to use Windows authentication, you must use extra care because user credentials are exposed in the connection string. In an ASP.NET application, you can configure a Windows account as a fixed identity that is used to connect to databases and other network resources. You enable impersonation in the identity element in the **web.config** file and specify a user name and password.
|
||||
For situations where it's not possible to use Windows authentication, you must use extra care because user credentials are exposed in the connection string. In an ASP.NET application, you can configure a Windows account as a fixed identity that is used to connect to databases and other network resources. You enable impersonation in the identity element in the **web.config** file and specify a user name and password.
|
||||
|
||||
```xml
|
||||
<identity impersonate="true"
|
||||
|
@ -22,23 +23,26 @@ Protecting access to your data source is one of the most important goals when se
|
|||
password="*****" />
|
||||
```
|
||||
|
||||
The fixed identity account should be a low-privilege account that has been granted only necessary permissions in the database. In addition, you should encrypt the configuration file so that the user name and password are not exposed in clear text.
|
||||
The fixed identity account should be a low-privilege account that has been granted only necessary permissions in the database. In addition, you should encrypt the configuration file so that the user name and password are not exposed in clear text.
|
||||
|
||||
## Do Not Use Universal Data Link (UDL) files
|
||||
> [!IMPORTANT]
|
||||
> Microsoft recommends that you use the most secure authentication flow available. The authentication flow described in this procedure requires a very high degree of trust in the application, and carries risks that are not present in other flows. You should only use this flow when other more secure flows, such as managed identities, aren't viable.
|
||||
|
||||
Avoid storing connection strings for an <xref:System.Data.OleDb.OleDbConnection> in a Universal Data Link (UDL) file. UDLs are stored in clear text and cannot be encrypted. A UDL file is an external file-based resource to your application, and it cannot be secured or encrypted using the .NET Framework.
|
||||
## Do not use Universal Data Link (UDL) files
|
||||
|
||||
Avoid storing connection strings for an <xref:System.Data.OleDb.OleDbConnection> in a Universal Data Link (UDL) file. UDLs are stored in clear text and cannot be encrypted. A UDL file is an external file-based resource to your application, and it cannot be secured or encrypted using .NET Framework.
|
||||
|
||||
## Avoid Injection Attacks with Connection String Builders
|
||||
|
||||
A connection string injection attack can occur when dynamic string concatenation is used to build connection strings based on user input. If the user input is not validated and malicious text or characters not escaped, an attacker can potentially access sensitive data or other resources on the server. To address this problem, ADO.NET 2.0 introduced new connection string builder classes to validate connection string syntax and ensure that additional parameters are not introduced. For more information, see [Connection String Builders](connection-string-builders.md).
|
||||
|
||||
## Use Persist Security Info=False
|
||||
## Use `Persist Security Info=False`
|
||||
|
||||
The default value for `Persist Security Info` is false; we recommend using this default in all connection strings. Setting `Persist Security Info` to `true` or `yes` allows security-sensitive information, including the user ID and password, to be obtained from a connection after it has been opened. When `Persist Security Info` is set to `false` or `no`, security information is discarded after it is used to open the connection, ensuring that an untrusted source does not have access to security-sensitive information.
|
||||
The default value for `Persist Security Info` is false; we recommend using this default in all connection strings. Setting `Persist Security Info` to `true` or `yes` allows security-sensitive information, including the user ID and password, to be obtained from a connection after it has been opened. When `Persist Security Info` is set to `false` or `no`, security information is discarded after it's used to open the connection, ensuring that an untrusted source does not have access to security-sensitive information.
|
||||
|
||||
## Encrypt Configuration Files
|
||||
|
||||
You can also store connection strings in configuration files, which eliminates the need to embed them in your application's code. Configuration files are standard XML files for which the .NET Framework has defined a common set of elements. Connection strings in configuration files are typically stored inside the **\<connectionStrings>** element in the **app.config** for a Windows application, or the **web.config** file for an ASP.NET application. For more information on the basics of storing, retrieving and encrypting connection strings from configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
You can also store connection strings in configuration files, which eliminates the need to embed them in your application's code. Configuration files are standard XML files for which .NET Framework has defined a common set of elements. Connection strings in configuration files are typically stored inside the **\<connectionStrings>** element in the **app.config** for a Windows application, or the **web.config** file for an ASP.NET application. For more information on the basics of storing, retrieving and encrypting connection strings from configuration files, see [Connection Strings and Configuration Files](connection-strings-and-configuration-files.md).
|
||||
|
||||
## See also
|
||||
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
---
|
||||
description: "Learn more about: REF CURSOR Parameters in an OracleDataReader"
|
||||
description: "Learn more about REF CURSOR parameters in an OracleDataReader by studying an example that executes a PL/SQL stored procedure."
|
||||
title: "REF CURSOR Parameters in an OracleDataReader"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
- "vb"
|
||||
ms.assetid: 801dff0f-2508-45aa-9416-f45d6887740c
|
||||
---
|
||||
# REF CURSOR Parameters in an OracleDataReader
|
||||
|
||||
This Microsoft Visual Basic example executes a PL/SQL stored procedure that returns a REF CURSOR parameter, and reads the value as an <xref:System.Data.OracleClient.OracleDataReader>.
|
||||
This Visual Basic example executes a PL/SQL stored procedure that returns a REF CURSOR parameter and reads the value as an <xref:System.Data.OracleClient.OracleDataReader>.
|
||||
|
||||
```vb
|
||||
Private Sub Button1_Click(ByVal sender As Object, _
|
||||
ByVal e As System.EventArgs) Handles Button1.Click
|
||||
|
||||
Dim connString As New String(_
|
||||
"Data Source=Oracle9i;User ID=scott;Password=[PLACEHOLDER];")
|
||||
Dim connString As New String("...")
|
||||
Using conn As New OracleConnection(connString)
|
||||
Dim cmd As New OracleCommand()
|
||||
Dim rdr As OracleDataReader
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
---
|
||||
description: "Learn more about: Retrieving Data from Multiple REF CURSORs Using an OracleDataReader"
|
||||
description: "Learn more about retrieving data from multiple REF CURSORs using an OracleDataReader by studying an example that executes a PL/SQL stored procedure."
|
||||
title: "Retrieving Data from Multiple REF CURSORs Using an OracleDataReader"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
- "vb"
|
||||
ms.assetid: 361e9bd4-447d-44b7-8629-3c11f1a7ffbb
|
||||
---
|
||||
# Retrieving Data from Multiple REF CURSORs Using an OracleDataReader
|
||||
|
||||
This Microsoft Visual Basic example executes a PL/SQL stored procedure that returns two REF CURSOR parameters, and reads the values using an <xref:System.Data.OracleClient.OracleDataReader>.
|
||||
This Visual Basic example executes a PL/SQL stored procedure that returns two REF CURSOR parameters, and reads the values using an <xref:System.Data.OracleClient.OracleDataReader>.
|
||||
|
||||
```vb
|
||||
Private Sub Button1_Click( _
|
||||
ByVal sender As Object, ByVal e As System.EventArgs) _
|
||||
Handles Button1.Click
|
||||
|
||||
Dim connString As New String( _
|
||||
"Data Source=Oracle9i;User ID=scott;Password=[PLACEHOLDER];")
|
||||
Dim connString As New String("...")
|
||||
Using conn As New OracleConnection(connString)
|
||||
Dim cmd As New OracleCommand()
|
||||
Dim rdr As OracleDataReader
|
||||
|
|
|
@ -5,10 +5,9 @@ ms.date: "03/30/2017"
|
|||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: d6b7f9cb-81be-44e1-bb94-56137954876d
|
||||
---
|
||||
|
||||
# Retrieving Identity or Autonumber Values
|
||||
# Retrieve identity or autonumber values
|
||||
|
||||
A primary key in a relational database is a column or combination of columns that always contain unique values. Knowing the primary key value allows you to locate the row that contains it. Relational database engines, such as SQL Server, Oracle, and Microsoft Access/Jet support the creation of automatically incrementing columns that can be designated as primary keys. These values are generated by the server as rows are added to a table. In SQL Server, you set the identity property of a column, in Oracle you create a Sequence, and in Microsoft Access you create an AutoNumber column.
|
||||
|
||||
|
@ -360,7 +359,7 @@ using System.Data.SqlClient;
|
|||
|
||||
class Program {
|
||||
static void Main(string[] args) {
|
||||
String SqlDbConnectionString = "Data Source=(local);Initial Catalog=MySchool;Integrated Security=True;Asynchronous Processing=true;";
|
||||
String SqlDbConnectionString = "...";
|
||||
|
||||
InsertPerson(SqlDbConnectionString, "Janice", "Galvin");
|
||||
Console.WriteLine();
|
||||
|
@ -368,7 +367,7 @@ class Program {
|
|||
InsertPersonInAdapter(SqlDbConnectionString, "Peter", "Krebs");
|
||||
Console.WriteLine();
|
||||
|
||||
String oledbConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=Database\\MySchool.mdb";
|
||||
String oledbConnectionString = "...";
|
||||
InsertPersonInJet4Database(oledbConnectionString, "Janice", "Galvin");
|
||||
Console.WriteLine();
|
||||
|
||||
|
|
|
@ -1,266 +1,253 @@
|
|||
---
|
||||
description: "Learn more about: Schema Restrictions"
|
||||
description: "Learn more about schema restrictions, which are used to limit the amount of schema information returned from the GetSchema method."
|
||||
title: "Schema Restrictions"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 73d2980e-e73c-4987-913a-8ddc93d09144
|
||||
---
|
||||
# Schema Restrictions
|
||||
# Schema restrictions
|
||||
|
||||
The second optional parameter of the **GetSchema** method is the restrictions that are used to limit the amount of schema information returned, and it is passed to the **GetSchema** method as an array of strings. The position in the array determines the values that you can pass, and this is equivalent to the restriction number.
|
||||
|
||||
For example, the following table describes the restrictions supported by the "Tables" schema collection using the .NET Framework Data Provider for SQL Server. Additional restrictions for SQL Server schema collections are listed at the end of this topic.
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Name|TABLE_NAME|3|
|
||||
|TableType|@TableType|TABLE_TYPE|4|
|
||||
|
||||
## Specifying Restriction Values
|
||||
The second optional parameter of the `GetSchema` method is the restrictions that are used to limit the amount of schema information returned. It's passed to the `GetSchema` method as an array of strings. The position in the array determines the values that you can pass, and this is equivalent to the restriction number.
|
||||
|
||||
For example, the following table describes the restrictions supported by the "Tables" schema collection using .NET Framework Data Provider for SQL Server. Additional restrictions for SQL Server schema collections are listed at the end of this article.
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Name | TABLE_NAME | 3 |
|
||||
| TableType | @TableType | TABLE_TYPE | 4 |
|
||||
|
||||
## Specifying Restriction Values
|
||||
|
||||
To use one of the restrictions of the "Tables" schema collection, simply create an array of strings with four elements, then place a value in the element that matches the restriction number. For example, to restrict the tables returned by the **GetSchema** method to only those tables in the "Sales" schema, set the second element of the array to "Sales" before passing it to the **GetSchema** method.
|
||||
|
||||
To use one of the restrictions of the "Tables" schema collection, simply create an array of strings with four elements, then place a value in the element that matches the restriction number. For example, to restrict the tables returned by the **GetSchema** method to only those tables in the "Sales" schema, set the second element of the array to "Sales" before passing it to the **GetSchema** method.
|
||||
|
||||
> [!NOTE]
|
||||
> The restrictions collections for `SqlClient` and `OracleClient` have an additional `ParameterName` column. The restriction default column is still there for backwards compatibility, but is currently ignored. Parameterized queries rather than string replacement should be used to minimize the risk of an SQL injection attack when specifying restriction values.
|
||||
|
||||
> [!NOTE]
|
||||
> The number of elements in the array must be less than or equal to the number of restrictions supported for the specified schema collection else an <xref:System.ArgumentException> will be thrown. There can be fewer than the maximum number of restrictions. The missing restrictions are assumed to be null (unrestricted).
|
||||
|
||||
You can query a .NET Framework managed provider to determine the list of supported restrictions by calling the **GetSchema** method with the name of the restrictions schema collection, which is "Restrictions". This will return a <xref:System.Data.DataTable> with a list of the collection names, the restriction names, the default restriction values, and the restriction numbers.
|
||||
|
||||
### Example
|
||||
> The restrictions collections for `SqlClient` and `OracleClient` have an additional `ParameterName` column. The restriction default column is still there for backwards compatibility, but is currently ignored. Parameterized queries rather than string replacement should be used to minimize the risk of an SQL injection attack when specifying restriction values.
|
||||
|
||||
The following examples demonstrate how to use the <xref:System.Data.SqlClient.SqlConnection.GetSchema%2A> method of the .NET Framework Data Provider for the SQL Server <xref:System.Data.SqlClient.SqlConnection> class to retrieve schema information about all of the tables contained in the **AdventureWorks** sample database, and to restrict the information returned to only those tables in the "Sales" schema:
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Module Module1
|
||||
Sub Main()
|
||||
Dim connectionString As String = _
|
||||
"Data Source=(local);Database=AdventureWorks;" & _
|
||||
"Integrated Security=true;";
|
||||
|
||||
Dim restrictions(3) As String
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
connection.Open()
|
||||
|
||||
'Specify the restrictions.
|
||||
restrictions(1) = "Sales"
|
||||
Dim table As DataTable = connection.GetSchema("Tables", _
|
||||
restrictions)
|
||||
|
||||
' Display the contents of the table.
|
||||
For Each row As DataRow In table.Rows
|
||||
For Each col As DataColumn In table.Columns
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row(col))
|
||||
Next
|
||||
Console.WriteLine("============================")
|
||||
Next
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Using
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
string connectionString =
|
||||
"Data Source=(local);Database=AdventureWorks;" +
|
||||
"Integrated Security=true;";
|
||||
using (SqlConnection connection =
|
||||
new SqlConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
// Specify the restrictions.
|
||||
string[] restrictions = new string[4];
|
||||
restrictions[1] = "Sales";
|
||||
System.Data.DataTable table = connection.GetSchema(
|
||||
"Tables", restrictions);
|
||||
|
||||
// Display the contents of the table.
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
> [!NOTE]
|
||||
> The number of elements in the array must be less than or equal to the number of restrictions supported for the specified schema collection else an <xref:System.ArgumentException> will be thrown. There can be fewer than the maximum number of restrictions. The missing restrictions are assumed to be null (unrestricted).
|
||||
|
||||
You can query a .NET Framework managed provider to determine the list of supported restrictions by calling the **GetSchema** method with the name of the restrictions schema collection, which is "Restrictions". This will return a <xref:System.Data.DataTable> with a list of the collection names, the restriction names, the default restriction values, and the restriction numbers.
|
||||
|
||||
### Example
|
||||
|
||||
The following examples demonstrate how to use the <xref:System.Data.SqlClient.SqlConnection.GetSchema%2A> method of the .NET Framework Data Provider for the SQL Server <xref:System.Data.SqlClient.SqlConnection> class to retrieve schema information about all of the tables contained in the **AdventureWorks** sample database, and to restrict the information returned to only those tables in the "Sales" schema:
|
||||
|
||||
```vb
|
||||
Imports System.Data.SqlClient
|
||||
|
||||
Module Module1
|
||||
Sub Main()
|
||||
Dim connectionString As String = "...";
|
||||
|
||||
Dim restrictions(3) As String
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
connection.Open()
|
||||
|
||||
'Specify the restrictions.
|
||||
restrictions(1) = "Sales"
|
||||
Dim table As DataTable = connection.GetSchema("Tables", _
|
||||
restrictions)
|
||||
|
||||
' Display the contents of the table.
|
||||
For Each row As DataRow In table.Rows
|
||||
For Each col As DataColumn In table.Columns
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row(col))
|
||||
Next
|
||||
Console.WriteLine("============================")
|
||||
Next
|
||||
Console.WriteLine("Press any key to continue.")
|
||||
Console.ReadKey()
|
||||
End Using
|
||||
End Sub
|
||||
End Module
|
||||
```
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
using System.Data;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
string connectionString ="...";
|
||||
using (SqlConnection connection =
|
||||
new SqlConnection(connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
|
||||
// Specify the restrictions.
|
||||
string[] restrictions = new string[4];
|
||||
restrictions[1] = "Sales";
|
||||
System.Data.DataTable table = connection.GetSchema(
|
||||
"Tables", restrictions);
|
||||
|
||||
// Display the contents of the table.
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
Console.WriteLine("{0} = {1}",
|
||||
col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetConnectionString()
|
||||
{
|
||||
// To avoid storing the connection string in your code,
|
||||
// you can retrieve it from a configuration file.
|
||||
return "Data Source=(local);Database=AdventureWorks;" +
|
||||
"Integrated Security=true;";
|
||||
}
|
||||
|
||||
private static void DisplayData(System.Data.DataTable table)
|
||||
{
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SQL Server Schema Restrictions
|
||||
col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
Console.WriteLine("Press any key to continue.");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
|
||||
The following tables list the restrictions for SQL Server schema collections.
|
||||
|
||||
### Users
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|User_Name|@Name|name|1|
|
||||
|
||||
### Databases
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Name|@Name|Name|1|
|
||||
|
||||
### Tables
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Name|TABLE_NAME|3|
|
||||
|TableType|@TableType|TABLE_TYPE|4|
|
||||
|
||||
### Columns
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|Column|@Column|COLUMN_NAME|4|
|
||||
|
||||
### StructuredTypeMembers
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|Column|@Column|COLUMN_NAME|4|
|
||||
|
||||
### Views
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|
||||
### ViewColumns
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|VIEW_CATALOG|1|
|
||||
|Owner|@Owner|VIEW_SCHEMA|2|
|
||||
|Table|@Table|VIEW_NAME|3|
|
||||
|Column|@Column|COLUMN_NAME|4|
|
||||
|
||||
### ProcedureParameters
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|SPECIFIC_CATALOG|1|
|
||||
|Owner|@Owner|SPECIFIC_SCHEMA|2|
|
||||
|Name|@Name|SPECIFIC_NAME|3|
|
||||
|Parameter|@Parameter|PARAMETER_NAME|4|
|
||||
|
||||
### Procedures
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|SPECIFIC_CATALOG|1|
|
||||
|Owner|@Owner|SPECIFIC_SCHEMA|2|
|
||||
|Name|@Name|SPECIFIC_NAME|3|
|
||||
|Type|@Type|ROUTINE_TYPE|4|
|
||||
|
||||
### IndexColumns
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|db_name()|1|
|
||||
|Owner|@Owner|user_name()|2|
|
||||
|Table|@Table|o.name|3|
|
||||
|ConstraintName|@ConstraintName|x.name|4|
|
||||
|Column|@Column|c.name|5|
|
||||
|
||||
### Indexes
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|db_name()|1|
|
||||
|Owner|@Owner|user_name()|2|
|
||||
|Table|@Table|o.name|3|
|
||||
|
||||
### UserDefinedTypes
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|assembly_name|@AssemblyName|assemblies.name|1|
|
||||
|udt_name|@UDTName|types.assembly_class|2|
|
||||
|
||||
### ForeignKeys
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|CONSTRAINT_CATALOG|1|
|
||||
|Owner|@Owner|CONSTRAINT_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|Name|@Name|CONSTRAINT_NAME|4|
|
||||
|
||||
## SQL Server 2008 Schema Restrictions
|
||||
private static void DisplayData(System.Data.DataTable table)
|
||||
{
|
||||
foreach (System.Data.DataRow row in table.Rows)
|
||||
{
|
||||
foreach (System.Data.DataColumn col in table.Columns)
|
||||
{
|
||||
Console.WriteLine("{0} = {1}", col.ColumnName, row[col]);
|
||||
}
|
||||
Console.WriteLine("============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## SQL Server Schema Restrictions
|
||||
|
||||
The following tables list the restrictions for SQL Server schema collections.
|
||||
|
||||
### Users
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| User_Name | @Name | name | 1 |
|
||||
|
||||
### Databases
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Name | @Name | Name | 1 |
|
||||
|
||||
### Tables
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Name | TABLE_NAME | 3 |
|
||||
| TableType | @TableType | TABLE_TYPE | 4 |
|
||||
|
||||
### Columns
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
| Column | @Column | COLUMN_NAME | 4 |
|
||||
|
||||
### StructuredTypeMembers
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
| Column | @Column | COLUMN_NAME | 4 |
|
||||
|
||||
### Views
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
|
||||
### ViewColumns
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | VIEW_CATALOG | 1 |
|
||||
| Owner | @Owner | VIEW_SCHEMA | 2 |
|
||||
| Table | @Table | VIEW_NAME | 3 |
|
||||
| Column | @Column | COLUMN_NAME | 4 |
|
||||
|
||||
### ProcedureParameters
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | SPECIFIC_CATALOG | 1 |
|
||||
| Owner | @Owner | SPECIFIC_SCHEMA | 2 |
|
||||
| Name | @Name | SPECIFIC_NAME | 3 |
|
||||
| Parameter | @Parameter | PARAMETER_NAME | 4 |
|
||||
|
||||
### Procedures
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | SPECIFIC_CATALOG | 1 |
|
||||
| Owner | @Owner | SPECIFIC_SCHEMA | 2 |
|
||||
| Name | @Name | SPECIFIC_NAME | 3 |
|
||||
| Type | @Type | ROUTINE_TYPE | 4 |
|
||||
|
||||
### IndexColumns
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|-----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | db_name() | 1 |
|
||||
| Owner | @Owner | user_name() | 2 |
|
||||
| Table | @Table | o.name | 3 |
|
||||
| ConstraintName | @ConstraintName | x.name | 4 |
|
||||
| Column | @Column | c.name | 5 |
|
||||
|
||||
### Indexes
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | db_name() | 1 |
|
||||
| Owner | @Owner | user_name() | 2 |
|
||||
| Table | @Table | o.name | 3 |
|
||||
|
||||
### UserDefinedTypes
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|----------------------|--------------------|
|
||||
| assembly_name | @AssemblyName | assemblies.name | 1 |
|
||||
| udt_name | @UDTName | types.assembly_class | 2 |
|
||||
|
||||
### ForeignKeys
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | CONSTRAINT_CATALOG | 1 |
|
||||
| Owner | @Owner | CONSTRAINT_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
| Name | @Name | CONSTRAINT_NAME | 4 |
|
||||
|
||||
## SQL Server 2008 Schema Restrictions
|
||||
|
||||
The following tables list the restrictions for SQL Server 2008 schema collections. These restrictions are valid beginning with version 3.5 SP1 of the .NET Framework and SQL Server 2008. They are not supported in earlier versions of the .NET Framework and SQL Server.
|
||||
|
||||
### ColumnSetColumns
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
|
||||
### AllColumns
|
||||
|
||||
| Restriction Name | Parameter Name | Restriction Default | Restriction Number |
|
||||
|------------------|----------------|---------------------|--------------------|
|
||||
| Catalog | @Catalog | TABLE_CATALOG | 1 |
|
||||
| Owner | @Owner | TABLE_SCHEMA | 2 |
|
||||
| Table | @Table | TABLE_NAME | 3 |
|
||||
| Column | @Column | COLUMN_NAME | 4 |
|
||||
|
||||
The following tables list the restrictions for SQL Server 2008 schema collections. These restrictions are valid beginning with version 3.5 SP1 of the .NET Framework and SQL Server 2008. They are not supported in earlier versions of the .NET Framework and SQL Server.
|
||||
|
||||
### ColumnSetColumns
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|
||||
### AllColumns
|
||||
|
||||
|Restriction Name|Parameter Name|Restriction Default|Restriction Number|
|
||||
|----------------------|--------------------|-------------------------|------------------------|
|
||||
|Catalog|@Catalog|TABLE_CATALOG|1|
|
||||
|Owner|@Owner|TABLE_SCHEMA|2|
|
||||
|Table|@Table|TABLE_NAME|3|
|
||||
|Column|@Column|COLUMN_NAME|4|
|
||||
|
||||
## See also
|
||||
|
||||
- [ADO.NET Overview](ado-net-overview.md)
|
||||
|
|
|
@ -1,100 +1,71 @@
|
|||
---
|
||||
description: "Learn more about: Secure Data Access"
|
||||
description: "Learn more about secure data access and understand the security mechanisms available in the underlying data store or database."
|
||||
title: "Secure Data Access"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: 473ebd69-21a3-4627-b95e-4e04d035c56f
|
||||
---
|
||||
# Secure Data Access
|
||||
# Secure data access
|
||||
|
||||
To write secure ADO.NET code, you have to understand the security mechanisms available in the underlying data store, or database. You also need to consider the security implications of other features or components that your application may contain.
|
||||
|
||||
## Authentication, Authorization and Permissions
|
||||
To write secure ADO.NET code, you have to understand the security mechanisms available in the underlying data store, or database. You also need to consider the security implications of other features or components that your application might contain.
|
||||
|
||||
When connecting to Microsoft SQL Server, you can use Windows Authentication, also known as Integrated Security, which uses the identity of the current active Windows user rather than passing a user ID and password. Using Windows Authentication is highly recommended because user credentials are not exposed in the connection string. If you cannot use Windows Authentication to connect to SQL Server, then consider creating connection strings at run time using the <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
|
||||
The credentials used for authentication need to be handled differently based on the type of application. For example, in a Windows Forms application, the user can be prompted to supply authentication information, or the user's Windows credentials can be used. However, a Web application often accesses data using credentials supplied by the application itself rather than by the user.
|
||||
|
||||
Once users have been authenticated, the scope of their actions depends on the permissions that have been granted to them. Always follow the principle of least privilege and grant only permissions that are absolutely necessary.
|
||||
|
||||
For more information, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Protecting Connection Information](protecting-connection-information.md)|Describes security best practices and techniques for protecting connection information, such as using protected configuration to encrypt connection strings.|
|
||||
|[Recommendations for Data Access Strategies](/previous-versions/visualstudio/visual-studio-2008/8fxztkff(v=vs.90))|Provides recommendations for accessing data and performing database operations.|
|
||||
|[Connection String Builders](connection-string-builders.md)|Describes how to build connection strings from user input at run time.|
|
||||
|[Overview of SQL Server Security](/previous-versions/dotnet/framework/data/adonet/sql/overview-of-sql-server-security)|Describes the SQL Server security architecture.|
|
||||
|
||||
## Parameterized Commands and SQL Injection
|
||||
## Authentication, Authorization, and Permissions
|
||||
|
||||
Using parameterized commands helps guard against SQL injection attacks, in which an attacker "injects" a command into a SQL statement that compromises security on the server. Parameterized commands guard against a SQL injection attack by ensuring that values received from an external source are passed as values only, and not part of the Transact-SQL statement. As a result, Transact-SQL commands inserted into a value are not executed at the data source. Rather, they are evaluated solely as a parameter value. In addition to the security benefits, parameterized commands provide a convenient method for organizing values passed with a Transact-SQL statement or to a stored procedure.
|
||||
|
||||
For more information on using parameterized commands, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[DataAdapter Parameters](dataadapter-parameters.md)|Describes how to use parameters with a `DataAdapter`.|
|
||||
|[Modifying Data with Stored Procedures](modifying-data-with-stored-procedures.md)|Describes how to specify parameters and obtain a return value.|
|
||||
|[Managing Permissions with Stored Procedures in SQL Server](/previous-versions/dotnet/framework/data/adonet/sql/managing-permissions-with-stored-procedures-in-sql-server)|Describes how to use SQL Server stored procedures to encapsulate data access.|
|
||||
|
||||
## Script Exploits
|
||||
When connecting to Microsoft SQL Server, you can use Windows Authentication, also known as Integrated Security, which uses the identity of the current active Windows user rather than passing a user ID and password. Using Windows Authentication is recommended for on-premises databases because user credentials aren't exposed in the connection string. If you can't use Windows Authentication to connect to SQL Server, then consider creating connection strings at run time using the <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
|
||||
A script exploit is another form of injection that uses malicious characters inserted into a Web page. The browser does not validate the inserted characters and will process them as part of the page.
|
||||
|
||||
For more information, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Script Exploits Overview](/previous-versions/aspnet/w1sw53ds(v=vs.100))|Describes how to guard against scripting and SQL statement exploits.|
|
||||
|
||||
## Probing Attacks
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
Attackers often use information from an exception, such as the name of your server, database, or table, to mount an attack on your system. Because exceptions can contain specific information about your application or data source, you can help keep your application and data source better protected by only exposing essential information to the client.
|
||||
|
||||
For more information, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Handling and throwing exceptions in .NET](../../../standard/exceptions/index.md)|Describes the basic forms of try/catch/finally structured exception handling.|
|
||||
|[Best Practices for Exceptions](../../../standard/exceptions/best-practices-for-exceptions.md)|Describes best practices for handling exceptions.|
|
||||
|
||||
## Protecting Microsoft Access and Excel Data Sources
|
||||
The credentials used for authentication need to be handled differently based on the type of application. For example, in a Windows Forms application, the user can be prompted to supply authentication information, or the user's Windows credentials can be used. However, a Web application often accesses data using credentials supplied by the application itself rather than by the user.
|
||||
|
||||
Microsoft Access and Microsoft Excel can act as a data store for an ADO.NET application when security requirements are minimal or nonexistent. Their security features are effective for deterrence, but should not be relied upon to do more than discourage meddling by uninformed users. The physical data files for Access and Excel exist on the file system, and must be accessible to all users. This makes them vulnerable to attacks that could result in theft or data loss since the files can be easily copied or altered. When robust security is required, use SQL Server or another server-based database where the physical data files are not readable from the file system.
|
||||
|
||||
For more information on protecting Access and Excel data, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Security Considerations and Guidance for Access 2007](/previous-versions/office/developer/office-2007/bb421308(v=office.12))|Describes security techniques for Access 2007 such encrypting files, administering passwords, converting databases to the new ACCDB and ACCDE formats, and using other security options.|
|
||||
|[Introduction to Access 2010 security](https://support.office.com/article/Introduction-to-Access-2010-security-CAE6D764-0318-4622-955F-68D9F186D6CA)|Provides an overview of the security features offered by Access 2010.|
|
||||
Once users have been authenticated, the scope of their actions depends on the permissions that have been granted to them. Always follow the principle of least privilege and grant only permissions that are absolutely necessary.
|
||||
|
||||
## Enterprise Services
|
||||
For more information, see the following resources.
|
||||
|
||||
COM+ contains its own security model that relies on Windows accounts and process/thread impersonation. The <xref:System.EnterpriseServices> namespace provides wrappers that allow .NET applications to integrate managed code with COM+ security services through the <xref:System.EnterpriseServices.ServicedComponent> class.
|
||||
|
||||
For more information, see the following resource.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Role-Based Security](/previous-versions/dotnet/netframework-1.1/s6y8k15h(v=vs.71))|Discusses how to integrate managed code with COM+ security services.|
|
||||
|
||||
## Interoperating with Unmanaged Code
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Protecting Connection Information](protecting-connection-information.md)|Describes security best practices and techniques for protecting connection information, such as using protected configuration to encrypt connection strings.|
|
||||
|[Connection String Builders](connection-string-builders.md)|Describes how to build connection strings from user input at run time.|
|
||||
|[Security for SQL Server Database Engine and Azure SQL Database](/sql/relational-databases/security/security-center-for-sql-server-database-engine-and-azure-sql-database)|Provides links to help you locate information about security and protection in the SQL Server Database Engine and Azure SQL Database.|
|
||||
|
||||
The .NET Framework provides for interaction with unmanaged code, including COM components, COM+ services, external type libraries, and many operating system services. Working with unmanaged code involves going outside the security perimeter for managed code. Both your code and any code that calls it must have unmanaged code permission (<xref:System.Security.Permissions.SecurityPermission> with the <xref:System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode> flag specified). Unmanaged code can introduce unintended security vulnerabilities into your application. Therefore, you should avoid interoperating with unmanaged code unless it is absolutely necessary.
|
||||
|
||||
For more information, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Interoperating with Unmanaged Code](../../interop/index.md)|Contains topics describing how to expose COM components to the .NET Framework and how to expose .NET Framework components to COM.|
|
||||
|[Advanced COM Interoperability](/previous-versions/dotnet/netframework-4.0/bd9cdfyx(v=vs.100))|Contains advanced topics such as primary interop assemblies, threading and custom marshalling.|
|
||||
## Parameterized Commands and SQL Injection
|
||||
|
||||
Using parameterized commands helps guard against SQL injection attacks, in which an attacker "injects" a command into a SQL statement that compromises security on the server. Parameterized commands guard against a SQL injection attack by ensuring that values received from an external source are passed as values only, and not part of the Transact-SQL statement. As a result, Transact-SQL commands inserted into a value are not executed at the data source. Rather, they are evaluated solely as a parameter value. In addition to the security benefits, parameterized commands provide a convenient method for organizing values passed with a Transact-SQL statement or to a stored procedure.
|
||||
|
||||
For more information on using parameterized commands, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[DataAdapter Parameters](dataadapter-parameters.md)|Describes how to use parameters with a `DataAdapter`.|
|
||||
|[Modifying Data with Stored Procedures](modifying-data-with-stored-procedures.md)|Describes how to specify parameters and obtain a return value.|
|
||||
|[Stored procedures (Database Engine)](/sql/relational-databases/stored-procedures/stored-procedures-database-engine)|Describes the benefits of using stored procedures and the different types of stored procedures.|
|
||||
|
||||
## Probing Attacks
|
||||
|
||||
Attackers often use information from an exception, such as the name of your server, database, or table, to mount an attack on your system. Because exceptions can contain specific information about your application or data source, you can help keep your application and data source better protected by only exposing essential information to the client.
|
||||
|
||||
For more information, see the following resources.
|
||||
|
||||
|Resource|Description|
|
||||
|--------------|-----------------|
|
||||
|[Handling and throwing exceptions in .NET](../../../standard/exceptions/index.md)|Describes the basic forms of try/catch/finally structured exception handling.|
|
||||
|[Best Practices for Exceptions](../../../standard/exceptions/best-practices-for-exceptions.md)|Describes best practices for handling exceptions.|
|
||||
|
||||
## Protect Microsoft Access and Excel Data Sources
|
||||
|
||||
Microsoft Access and Microsoft Excel can act as a data store for an ADO.NET application when security requirements are minimal or nonexistent. Their security features are effective for deterrence, but should not be relied upon to do more than discourage meddling by uninformed users. The physical data files for Access and Excel exist on the file system, and must be accessible to all users. This makes them vulnerable to attacks that could result in theft or data loss since the files can be easily copied or altered. When robust security is required, use SQL Server or another server-based database where the physical data files are not readable from the file system.
|
||||
|
||||
## Enterprise Services
|
||||
|
||||
COM+ contains its own security model that relies on Windows accounts and process/thread impersonation. The <xref:System.EnterpriseServices> namespace provides wrappers that allow .NET applications to integrate managed code with COM+ security services through the <xref:System.EnterpriseServices.ServicedComponent> class.
|
||||
|
||||
## Interoperate with Unmanaged Code
|
||||
|
||||
.NET Framework provides for interaction with unmanaged code, including COM components, COM+ services, external type libraries, and many operating system services. Working with unmanaged code involves going outside the security perimeter for managed code. Both your code and any code that calls it must have unmanaged code permission (<xref:System.Security.Permissions.SecurityPermission> with the <xref:System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode> flag specified). Unmanaged code can introduce unintended security vulnerabilities into your application. Therefore, you should avoid interoperating with unmanaged code unless it is absolutely necessary.
|
||||
|
||||
For more information, see [Interoperating with Unmanaged Code](../../interop/index.md).
|
||||
|
||||
## See also
|
||||
|
||||
- [Securing ADO.NET Applications](securing-ado-net-applications.md)
|
||||
- [SQL Server Security](/previous-versions/dotnet/framework/data/adonet/sql/sql-server-security)
|
||||
- [Recommendations for Data Access Strategies](/previous-versions/visualstudio/visual-studio-2008/8fxztkff(v=vs.90))
|
||||
- [Protecting Connection Information](protecting-connection-information.md)
|
||||
- [Connection String Builders](connection-string-builders.md)
|
||||
- [ADO.NET Overview](ado-net-overview.md)
|
||||
|
|
|
@ -2,140 +2,135 @@
|
|||
title: "SQL Server Connection Pooling"
|
||||
description: Learn how ADO.NET minimizes the cost of opening connections by using SQL Server connection pooling, which reduces overhead for new connections.
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: 7e51d44e-7c4e-4040-9332-f0190fe36f07
|
||||
---
|
||||
# SQL Server Connection Pooling (ADO.NET)
|
||||
|
||||
Connecting to a database server typically consists of several time-consuming steps. A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on.
|
||||
|
||||
In practice, most applications use only one or a few different configurations for connections. This means that during application execution, many identical connections will be repeatedly opened and closed. To minimize the cost of opening connections, ADO.NET uses an optimization technique called *connection pooling*.
|
||||
|
||||
Connection pooling reduces the number of times that new connections must be opened. The *pooler* maintains ownership of the physical connection. It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls `Open` on a connection, the pooler looks for an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls `Close` on the connection, the pooler returns it to the pooled set of active connections instead of closing it. Once the connection is returned to the pool, it is ready to be reused on the next `Open` call.
|
||||
|
||||
Only connections with the same configuration can be pooled. ADO.NET keeps several pools at the same time, one for each configuration. Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Connections are also pooled based on whether they are enlisted in a transaction. When using <xref:System.Data.SqlClient.SqlConnection.ChangePassword%2A>, the <xref:System.Data.SqlClient.SqlCredential> instance affects the connection pool. Different instances of <xref:System.Data.SqlClient.SqlCredential> will use different connection pools, even if the user ID and password are the same.
|
||||
|
||||
Pooling connections can significantly enhance the performance and scalability of your application. By default, connection pooling is enabled in ADO.NET. Unless you explicitly disable it, the pooler optimizes the connections as they are opened and closed in your application. You can also supply several connection string modifiers to control connection pooling behavior. For more information, see "Controlling Connection Pooling with Connection String Keywords" later in this topic.
|
||||
|
||||
> [!NOTE]
|
||||
> When connection pooling is enabled, and if a timeout error or other login error occurs, an exception will be thrown and subsequent connection attempts will fail for the next five seconds, the "blocking period". If the application attempts to connect within the blocking period, the first exception will be thrown again. Subsequent failures after a blocking period ends will result in a new blocking periods that is twice as long as the previous blocking period, up to a maximum of one minute.
|
||||
|
||||
## Pool Creation and Assignment
|
||||
Connecting to a database server typically consists of several time-consuming steps. A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on.
|
||||
|
||||
In practice, most applications use only one or a few different configurations for connections. This means that during application execution, many identical connections will be repeatedly opened and closed. To minimize the cost of opening connections, ADO.NET uses an optimization technique called *connection pooling*.
|
||||
|
||||
Connection pooling reduces the number of times that new connections must be opened. The *pooler* maintains ownership of the physical connection. It manages connections by keeping alive a set of active connections for each given connection configuration. Whenever a user calls `Open` on a connection, the pooler looks for an available connection in the pool. If a pooled connection is available, it returns it to the caller instead of opening a new connection. When the application calls `Close` on the connection, the pooler returns it to the pooled set of active connections instead of closing it. Once the connection is returned to the pool, it is ready to be reused on the next `Open` call.
|
||||
|
||||
Only connections with the same configuration can be pooled. ADO.NET keeps several pools at the same time, one for each configuration. Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Connections are also pooled based on whether they are enlisted in a transaction. When using <xref:System.Data.SqlClient.SqlConnection.ChangePassword%2A>, the <xref:System.Data.SqlClient.SqlCredential> instance affects the connection pool. Different instances of <xref:System.Data.SqlClient.SqlCredential> will use different connection pools, even if the user ID and password are the same.
|
||||
|
||||
Pooling connections can significantly enhance the performance and scalability of your application. By default, connection pooling is enabled in ADO.NET. Unless you explicitly disable it, the pooler optimizes the connections as they are opened and closed in your application. You can also supply several connection string modifiers to control connection pooling behavior. For more information, see "Controlling Connection Pooling with Connection String Keywords" later in this topic.
|
||||
|
||||
> [!NOTE]
|
||||
> When connection pooling is enabled, and if a timeout error or other login error occurs, an exception will be thrown and subsequent connection attempts will fail for the next five seconds, the "blocking period". If the application attempts to connect within the blocking period, the first exception will be thrown again. Subsequent failures after a blocking period ends will result in a new blocking periods that is twice as long as the previous blocking period, up to a maximum of one minute.
|
||||
|
||||
## Pool Creation and Assignment
|
||||
|
||||
When a connection is first opened, a connection pool is created based on an exact matching algorithm that associates the pool with the connection string in the connection. Each connection pool is associated with a distinct connection string. When a new connection is opened, if the connection string is not an exact match to an existing pool, a new pool is created. Connections are pooled per process, per application domain, per connection string and when integrated security is used, per Windows identity. Connection strings must also be an exact match; keywords supplied in a different order for the same connection will be pooled separately.
|
||||
|
||||
In the following C# example, three new <xref:System.Data.SqlClient.SqlConnection> objects are created, but only two connection pools are required to manage them. Note that the first and second connection strings differ by the value assigned for `Initial Catalog`.
|
||||
|
||||
When a connection is first opened, a connection pool is created based on an exact matching algorithm that associates the pool with the connection string in the connection. Each connection pool is associated with a distinct connection string. When a new connection is opened, if the connection string is not an exact match to an existing pool, a new pool is created. Connections are pooled per process, per application domain, per connection string and when integrated security is used, per Windows identity. Connection strings must also be an exact match; keywords supplied in a different order for the same connection will be pooled separately.
|
||||
|
||||
In the following C# example, three new <xref:System.Data.SqlClient.SqlConnection> objects are created, but only two connection pools are required to manage them. Note that the first and second connection strings differ by the value assigned for `Initial Catalog`.
|
||||
|
||||
```csharp
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=Northwind"))
|
||||
{
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=Northwind"))
|
||||
{
|
||||
connection.Open();
|
||||
// Pool A is created.
|
||||
}
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=pubs"))
|
||||
{
|
||||
connection.Open();
|
||||
// Pool B is created because the connection strings differ.
|
||||
}
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=Northwind"))
|
||||
{
|
||||
connection.Open();
|
||||
// The connection string matches pool A.
|
||||
}
|
||||
```
|
||||
|
||||
If `Min Pool Size` is either not specified in the connection string or is specified as zero, the connections in the pool will be closed after a period of inactivity. However, if the specified `Min Pool Size` is greater than zero, the connection pool is not destroyed until the `AppDomain` is unloaded and the process ends. Maintenance of inactive or empty pools involves minimal system overhead.
|
||||
|
||||
> [!NOTE]
|
||||
> The pool is automatically cleared when a fatal error occurs, such as a failover.
|
||||
|
||||
## Adding Connections
|
||||
// Pool A is created.
|
||||
}
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=pubs"))
|
||||
{
|
||||
connection.Open();
|
||||
// Pool B is created because the connection strings differ.
|
||||
}
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
"Integrated Security=SSPI;Initial Catalog=Northwind"))
|
||||
{
|
||||
connection.Open();
|
||||
// The connection string matches pool A.
|
||||
}
|
||||
```
|
||||
|
||||
[!INCLUDE [managed-identities](../../includes/managed-identities.md)]
|
||||
|
||||
If `Min Pool Size` is either not specified in the connection string or is specified as zero, the connections in the pool will be closed after a period of inactivity. However, if the specified `Min Pool Size` is greater than zero, the connection pool is not destroyed until the `AppDomain` is unloaded and the process ends. Maintenance of inactive or empty pools involves minimal system overhead.
|
||||
|
||||
> [!NOTE]
|
||||
> The pool is automatically cleared when a fatal error occurs, such as a failover.
|
||||
|
||||
## Add Connections
|
||||
|
||||
A connection pool is created for each unique connection string. When a pool is created, multiple connection objects are created and added to the pool so that the minimum pool size requirement is satisfied. Connections are added to the pool as needed, up to the maximum pool size specified (100 is the default). Connections are released back into the pool when they are closed or disposed.
|
||||
|
||||
When a <xref:System.Data.SqlClient.SqlConnection> object is requested, it is obtained from the pool if a usable connection is available. To be usable, a connection must be unused, have a matching transaction context or be unassociated with any transaction context, and have a valid link to the server.
|
||||
|
||||
The connection pooler satisfies requests for connections by reallocating connections as they are released back into the pool. If the maximum pool size has been reached and no usable connection is available, the request is queued. The pooler then tries to reclaim any connections until the time-out is reached (the default is 15 seconds). If the pooler cannot satisfy the request before the connection times out, an exception is thrown.
|
||||
|
||||
A connection pool is created for each unique connection string. When a pool is created, multiple connection objects are created and added to the pool so that the minimum pool size requirement is satisfied. Connections are added to the pool as needed, up to the maximum pool size specified (100 is the default). Connections are released back into the pool when they are closed or disposed.
|
||||
|
||||
When a <xref:System.Data.SqlClient.SqlConnection> object is requested, it is obtained from the pool if a usable connection is available. To be usable, a connection must be unused, have a matching transaction context or be unassociated with any transaction context, and have a valid link to the server.
|
||||
|
||||
The connection pooler satisfies requests for connections by reallocating connections as they are released back into the pool. If the maximum pool size has been reached and no usable connection is available, the request is queued. The pooler then tries to reclaim any connections until the time-out is reached (the default is 15 seconds). If the pooler cannot satisfy the request before the connection times out, an exception is thrown.
|
||||
|
||||
> [!CAUTION]
|
||||
> We strongly recommend that you always close the connection when you are finished using it so that the connection will be returned to the pool. You can do this using either the `Close` or `Dispose` methods of the `Connection` object, or by opening all connections inside a `using` statement in C#, or a `Using` statement in Visual Basic. Connections that are not explicitly closed might not be added or returned to the pool. For more information, see [using statement](../../../csharp/language-reference/statements/using.md) or [How to: Dispose of a System Resource](../../../visual-basic/programming-guide/language-features/control-flow/how-to-dispose-of-a-system-resource.md) for Visual Basic.
|
||||
|
||||
> We strongly recommend that you always close the connection when you're finished using it so that the connection will be returned to the pool. You can do this using either the `Close` or `Dispose` methods of the `Connection` object, or by opening all connections inside a `using` statement in C#, or a `Using` statement in Visual Basic. Connections that are not explicitly closed might not be added or returned to the pool. For more information, see [using statement](../../../csharp/language-reference/statements/using.md) or [How to: Dispose of a System Resource](../../../visual-basic/programming-guide/language-features/control-flow/how-to-dispose-of-a-system-resource.md) for Visual Basic.
|
||||
|
||||
> [!NOTE]
|
||||
> Do not call `Close` or `Dispose` on a `Connection`, a `DataReader`, or any other managed object in the `Finalize` method of your class. In a finalizer, only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a `Finalize` method in your class definition. For more information, see [Garbage Collection](../../../standard/garbage-collection/index.md).
|
||||
|
||||
For more info about the events associated with opening and closing connections, see [Audit Login Event Class](/sql/relational-databases/event-classes/audit-login-event-class) and [Audit Logout Event Class](/sql/relational-databases/event-classes/audit-logout-event-class) in the SQL Server documentation.
|
||||
|
||||
## Removing Connections
|
||||
> Do not call `Close` or `Dispose` on a `Connection`, a `DataReader`, or any other managed object in the `Finalize` method of your class. In a finalizer, only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a `Finalize` method in your class definition. For more information, see [Garbage Collection](../../../standard/garbage-collection/index.md).
|
||||
|
||||
The connection pooler removes a connection from the pool after it has been idle for approximately 4-8 minutes, or if the pooler detects that the connection with the server has been severed. Note that a severed connection can be detected only after attempting to communicate with the server. If a connection is found that is no longer connected to the server, it is marked as invalid. Invalid connections are removed from the connection pool only when they are closed or reclaimed.
|
||||
|
||||
If a connection exists to a server that has disappeared, this connection can be drawn from the pool even if the connection pooler has not detected the severed connection and marked it as invalid. This is the case because the overhead of checking that the connection is still valid would eliminate the benefits of having a pooler by causing another round trip to the server to occur. When this occurs, the first attempt to use the connection will detect that the connection has been severed, and an exception is thrown.
|
||||
|
||||
## Clearing the Pool
|
||||
For more info about the events associated with opening and closing connections, see [Audit Login Event Class](/sql/relational-databases/event-classes/audit-login-event-class) and [Audit Logout Event Class](/sql/relational-databases/event-classes/audit-logout-event-class) in the SQL Server documentation.
|
||||
|
||||
ADO.NET 2.0 introduced two new methods to clear the pool: <xref:System.Data.SqlClient.SqlConnection.ClearAllPools%2A> and <xref:System.Data.SqlClient.SqlConnection.ClearPool%2A>. `ClearAllPools` clears the connection pools for a given provider, and `ClearPool` clears the connection pool that is associated with a specific connection. If there are connections being used at the time of the call, they are marked appropriately. When they are closed, they are discarded instead of being returned to the pool.
|
||||
|
||||
## Transaction Support
|
||||
## Remove Connections
|
||||
|
||||
Connections are drawn from the pool and assigned based on transaction context. Unless `Enlist=false` is specified in the connection string, the connection pool makes sure that the connection is enlisted in the <xref:System.Transactions.Transaction.Current%2A> context. When a connection is closed and returned to the pool with an enlisted `System.Transactions` transaction, it is set aside in such a way that the next request for that connection pool with the same `System.Transactions` transaction will return the same connection if it is available. If such a request is issued, and there are no pooled connections available, a connection is drawn from the non-transacted part of the pool and enlisted. If no connections are available in either area of the pool, a new connection is created and enlisted.
|
||||
|
||||
When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. This allows you to commit or abort the distributed transaction later.
|
||||
|
||||
## Controlling Connection Pooling with Connection String Keywords
|
||||
The connection pooler removes a connection from the pool after it has been idle for approximately 4-8 minutes, or if the pooler detects that the connection with the server has been severed. Note that a severed connection can be detected only after attempting to communicate with the server. If a connection is found that is no longer connected to the server, it is marked as invalid. Invalid connections are removed from the connection pool only when they are closed or reclaimed.
|
||||
|
||||
The `ConnectionString` property of the <xref:System.Data.SqlClient.SqlConnection> object supports connection string key/value pairs that can be used to adjust the behavior of the connection pooling logic. For more information, see <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>.
|
||||
|
||||
## Pool Fragmentation
|
||||
If a connection exists to a server that has disappeared, this connection can be drawn from the pool even if the connection pooler has not detected the severed connection and marked it as invalid. This is the case because the overhead of checking that the connection is still valid would eliminate the benefits of having a pooler by causing another round trip to the server to occur. When this occurs, the first attempt to use the connection will detect that the connection has been severed, and an exception is thrown.
|
||||
|
||||
Pool fragmentation is a common problem in many Web applications where the application can create a large number of pools that are not freed until the process exits. This leaves a large number of connections open and consuming memory, which results in poor performance.
|
||||
|
||||
### Pool Fragmentation Due to Integrated Security
|
||||
## Clear the Pool
|
||||
|
||||
Connections are pooled according to the connection string plus the user identity. Therefore, if you use Basic authentication or Windows Authentication on the Web site and an integrated security login, you get one pool per user. Although this improves the performance of subsequent database requests for a single user, that user cannot take advantage of connections made by other users. It also results in at least one connection per user to the database server. This is a side effect of a particular Web application architecture that developers must weigh against security and auditing requirements.
|
||||
|
||||
### Pool Fragmentation Due to Many Databases
|
||||
ADO.NET 2.0 introduced two new methods to clear the pool: <xref:System.Data.SqlClient.SqlConnection.ClearAllPools%2A> and <xref:System.Data.SqlClient.SqlConnection.ClearPool%2A>. `ClearAllPools` clears the connection pools for a given provider, and `ClearPool` clears the connection pool that is associated with a specific connection. If there are connections being used at the time of the call, they are marked appropriately. When they are closed, they are discarded instead of being returned to the pool.
|
||||
|
||||
Many Internet service providers host several Web sites on a single server. They may use a single database to confirm a Forms authentication login and then open a connection to a specific database for that user or group of users. The connection to the authentication database is pooled and used by everyone. However, there is a separate pool of connections to each database, which increase the number of connections to the server.
|
||||
|
||||
This is also a side-effect of the application design. There is a relatively simple way to avoid this side effect without compromising security when you connect to SQL Server. Instead of connecting to a separate database for each user or group, connect to the same database on the server and then execute the Transact-SQL USE statement to change to the desired database. The following code fragment demonstrates creating an initial connection to the `master` database and then switching to the desired database specified in the `databaseName` string variable.
|
||||
|
||||
```vb
|
||||
' Assumes that command is a valid SqlCommand object and that
|
||||
' connectionString connects to master.
|
||||
command.Text = "USE DatabaseName"
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
connection.Open()
|
||||
command.ExecuteNonQuery()
|
||||
End Using
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Assumes that command is a SqlCommand object and that
|
||||
// connectionString connects to master.
|
||||
command.Text = "USE DatabaseName";
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
```
|
||||
|
||||
## Application Roles and Connection Pooling
|
||||
## Transaction Support
|
||||
|
||||
After a SQL Server application role has been activated by calling the `sp_setapprole` system stored procedure, the security context of that connection cannot be reset. However, if pooling is enabled, the connection is returned to the pool, and an error occurs when the pooled connection is reused. For more information, see the Knowledge Base article, "[SQL application role errors with OLE DB resource pooling](https://support.microsoft.com/default.aspx?scid=KB;EN-US;Q229564)."
|
||||
|
||||
### Application Role Alternatives
|
||||
Connections are drawn from the pool and assigned based on transaction context. Unless `Enlist=false` is specified in the connection string, the connection pool makes sure that the connection is enlisted in the <xref:System.Transactions.Transaction.Current%2A> context. When a connection is closed and returned to the pool with an enlisted `System.Transactions` transaction, it is set aside in such a way that the next request for that connection pool with the same `System.Transactions` transaction will return the same connection if it is available. If such a request is issued, and there are no pooled connections available, a connection is drawn from the non-transacted part of the pool and enlisted. If no connections are available in either area of the pool, a new connection is created and enlisted.
|
||||
|
||||
When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. This allows you to commit or abort the distributed transaction later.
|
||||
|
||||
## Control Connection Pooling with Connection String Keywords
|
||||
|
||||
The `ConnectionString` property of the <xref:System.Data.SqlClient.SqlConnection> object supports connection string key/value pairs that can be used to adjust the behavior of the connection pooling logic. For more information, see <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>.
|
||||
|
||||
## Pool Fragmentation
|
||||
|
||||
Pool fragmentation is a common problem in many Web applications where the application can create a large number of pools that are not freed until the process exits. This leaves a large number of connections open and consuming memory, which results in poor performance.
|
||||
|
||||
### Pool Fragmentation Due to Integrated Security
|
||||
|
||||
Connections are pooled according to the connection string plus the user identity. Therefore, if you use Basic authentication or Windows Authentication on the Web site and an integrated security login, you get one pool per user. Although this improves the performance of subsequent database requests for a single user, that user cannot take advantage of connections made by other users. It also results in at least one connection per user to the database server. This is a side effect of a particular Web application architecture that developers must weigh against security and auditing requirements.
|
||||
|
||||
### Pool Fragmentation Due to Many Databases
|
||||
|
||||
Many Internet service providers host several Web sites on a single server. They may use a single database to confirm a Forms authentication login and then open a connection to a specific database for that user or group of users. The connection to the authentication database is pooled and used by everyone. However, there is a separate pool of connections to each database, which increase the number of connections to the server.
|
||||
|
||||
This is also a side-effect of the application design. There is a relatively simple way to avoid this side effect without compromising security when you connect to SQL Server. Instead of connecting to a separate database for each user or group, connect to the same database on the server and then execute the Transact-SQL USE statement to change to the desired database. The following code fragment demonstrates creating an initial connection to the `master` database and then switching to the desired database specified in the `databaseName` string variable.
|
||||
|
||||
```vb
|
||||
' Assumes that command is a SqlCommand object.
|
||||
command.Text = "USE DatabaseName"
|
||||
Using connection As New SqlConnection(connectionString)
|
||||
connection.Open()
|
||||
command.ExecuteNonQuery()
|
||||
End Using
|
||||
```
|
||||
|
||||
```csharp
|
||||
// Assumes that command is a SqlCommand object.
|
||||
command.Text = "USE DatabaseName";
|
||||
using (SqlConnection connection = new SqlConnection(
|
||||
connectionString))
|
||||
{
|
||||
connection.Open();
|
||||
command.ExecuteNonQuery();
|
||||
}
|
||||
```
|
||||
|
||||
## Application Roles and Connection Pooling
|
||||
|
||||
After a SQL Server application role has been activated by calling the `sp_setapprole` system stored procedure, the security context of that connection cannot be reset. However, if pooling is enabled, the connection is returned to the pool, and an error occurs when the pooled connection is reused. For more information, see the Knowledge Base article, "[SQL application role errors with OLE DB resource pooling](https://support.microsoft.com/default.aspx?scid=KB;EN-US;Q229564)."
|
||||
|
||||
We recommend that you take advantage of security mechanisms that you can use instead of application roles. For more information, see [Creating Application Roles in SQL Server](/previous-versions/dotnet/framework/data/adonet/sql/creating-application-roles-in-sql-server).
|
||||
|
||||
## See also
|
||||
|
||||
- [Connection Pooling](connection-pooling.md)
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
---
|
||||
description: "Learn more about: SqlClient Streaming Support"
|
||||
description: "Learn more about streaming support between SQL Server and an application, which supports unstructured data on the server."
|
||||
title: "SqlClient Streaming Support"
|
||||
ms.date: "03/30/2017"
|
||||
ms.assetid: c449365b-470b-4edb-9d61-8353149f5531
|
||||
---
|
||||
|
||||
# SqlClient Streaming Support
|
||||
# SqlClient streaming support
|
||||
|
||||
Streaming support between SQL Server and an application (new in .NET Framework 4.5) supports unstructured data on the server (documents, images, and media files). A SQL Server database can store binary large objects (BLOBs), but retrieving BLOBS can use a lot of memory.
|
||||
|
||||
|
@ -24,25 +23,18 @@ Streaming support from SQL Server introduces new functionality in the <xref:Syst
|
|||
|
||||
The following members were added to <xref:System.Data.SqlClient.SqlDataReader> to enable streaming support from SQL Server:
|
||||
|
||||
1. <xref:System.Data.SqlClient.SqlDataReader.IsDBNullAsync%2A>
|
||||
|
||||
2. <xref:System.Data.SqlClient.SqlDataReader.GetFieldValue%2A?displayProperty=nameWithType>
|
||||
|
||||
3. <xref:System.Data.SqlClient.SqlDataReader.GetFieldValueAsync%2A>
|
||||
|
||||
4. <xref:System.Data.SqlClient.SqlDataReader.GetStream%2A>
|
||||
|
||||
5. <xref:System.Data.SqlClient.SqlDataReader.GetTextReader%2A>
|
||||
|
||||
6. <xref:System.Data.SqlClient.SqlDataReader.GetXmlReader%2A>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.IsDBNullAsync%2A>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.GetFieldValue%2A?displayProperty=nameWithType>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.GetFieldValueAsync%2A>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.GetStream%2A>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.GetTextReader%2A>
|
||||
- <xref:System.Data.SqlClient.SqlDataReader.GetXmlReader%2A>
|
||||
|
||||
The following members were added to <xref:System.Data.Common.DbDataReader> to enable streaming support from SQL Server:
|
||||
|
||||
1. <xref:System.Data.Common.DbDataReader.GetFieldValue%2A>
|
||||
|
||||
2. <xref:System.Data.Common.DbDataReader.GetStream%2A>
|
||||
|
||||
3. <xref:System.Data.Common.DbDataReader.GetTextReader%2A>
|
||||
- <xref:System.Data.Common.DbDataReader.GetFieldValue%2A>
|
||||
- <xref:System.Data.Common.DbDataReader.GetStream%2A>
|
||||
- <xref:System.Data.Common.DbDataReader.GetTextReader%2A>
|
||||
|
||||
## Streaming Support to SQL Server
|
||||
|
||||
|
@ -53,17 +45,13 @@ Disposing a <xref:System.Data.SqlClient.SqlCommand> object or calling <xref:Syst
|
|||
The following <xref:System.Data.SqlClient.SqlParameter.SqlDbType%2A> types will accept a <xref:System.Data.SqlClient.SqlParameter.Value%2A> of <xref:System.IO.Stream>:
|
||||
|
||||
- **Binary**
|
||||
|
||||
- **VarBinary**
|
||||
|
||||
The following <xref:System.Data.SqlClient.SqlParameter.SqlDbType%2A> types will accept a <xref:System.Data.SqlClient.SqlParameter.Value%2A> of <xref:System.IO.TextReader>:
|
||||
|
||||
- **Char**
|
||||
|
||||
- **NChar**
|
||||
|
||||
- **NVarChar**
|
||||
|
||||
- **Xml**
|
||||
|
||||
The **Xml**<xref:System.Data.SqlClient.SqlParameter.SqlDbType%2A> type will accept a <xref:System.Data.SqlClient.SqlParameter.Value%2A> of <xref:System.Xml.XmlReader>.
|
||||
|
@ -72,7 +60,7 @@ The **Xml**<xref:System.Data.SqlClient.SqlParameter.SqlDbType%2A> type will acce
|
|||
|
||||
The <xref:System.Xml.XmlReader>, <xref:System.IO.TextReader>, and <xref:System.IO.Stream> object will be transferred up to the value defined by the <xref:System.Data.SqlClient.SqlParameter.Size%2A>.
|
||||
|
||||
## Sample -- Streaming from SQL Server
|
||||
## Sample: Streaming from SQL Server
|
||||
|
||||
Use the following Transact-SQL to create the sample database:
|
||||
|
||||
|
@ -96,13 +84,9 @@ GO
|
|||
The sample shows how to do the following:
|
||||
|
||||
- Avoid blocking a user-interface thread by providing an asynchronous way to retrieve large files.
|
||||
|
||||
- Transfer a large text file from SQL Server in .NET Framework 4.5.
|
||||
|
||||
- Transfer a large XML file from SQL Server in .NET Framework 4.5.
|
||||
|
||||
- Retrieve data from SQL Server.
|
||||
|
||||
- Transfer large files (BLOBs) from one SQL Server database to another without running out of memory.
|
||||
|
||||
```csharp
|
||||
|
@ -115,8 +99,7 @@ using System.Xml;
|
|||
|
||||
namespace StreamingFromServer {
|
||||
class Program {
|
||||
// Replace the connection string if needed, for instance to connect to SQL Express: @"Server=(local)\SQLEXPRESS;Database=Demo;Integrated Security=true"
|
||||
private const string connectionString = @"Server=(localdb)\V11.0;Database=Demo";
|
||||
private const string connectionString = @"...";
|
||||
|
||||
static void Main(string[] args) {
|
||||
CopyBinaryValueToFile().Wait();
|
||||
|
@ -127,7 +110,7 @@ namespace StreamingFromServer {
|
|||
Console.WriteLine("Done");
|
||||
}
|
||||
|
||||
// Application retrieving a large BLOB from SQL Server in .NET Framework 4.5 using the new asynchronous capability
|
||||
// Retrieve a large BLOB from SQL Server in .NET Framework 4.5 using the asynchronous capability.
|
||||
private static async Task CopyBinaryValueToFile() {
|
||||
string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "binarydata.bin");
|
||||
|
||||
|
@ -136,15 +119,15 @@ namespace StreamingFromServer {
|
|||
using (SqlCommand command = new SqlCommand("SELECT [bindata] FROM [Streams] WHERE [id]=@id", connection)) {
|
||||
command.Parameters.AddWithValue("id", 1);
|
||||
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
|
||||
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming.
|
||||
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions.
|
||||
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess)) {
|
||||
if (await reader.ReadAsync()) {
|
||||
if (!(await reader.IsDBNullAsync(0))) {
|
||||
using (FileStream file = new FileStream(filePath, FileMode.Create, FileAccess.Write)) {
|
||||
using (Stream data = reader.GetStream(0)) {
|
||||
|
||||
// Asynchronously copy the stream from the server to the file we just created
|
||||
// Asynchronously copy the stream from the server to the file we just created.
|
||||
await data.CopyToAsync(file);
|
||||
}
|
||||
}
|
||||
|
@ -155,14 +138,14 @@ namespace StreamingFromServer {
|
|||
}
|
||||
}
|
||||
|
||||
// Application transferring a large Text File from SQL Server in .NET Framework 4.5
|
||||
// Transfer a large Text File from SQL Server in .NET Framework 4.5.
|
||||
private static async Task PrintTextValues() {
|
||||
using (SqlConnection connection = new SqlConnection(connectionString)) {
|
||||
await connection.OpenAsync();
|
||||
using (SqlCommand command = new SqlCommand("SELECT [id], [textdata] FROM [Streams]", connection)) {
|
||||
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
|
||||
// Otherwise ReadAsync will buffer the entire text document into memory which can cause scalability issues or even OutOfMemoryExceptions
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming.
|
||||
// Otherwise ReadAsync will buffer the entire text document into memory which can cause scalability issues or even OutOfMemoryExceptions.
|
||||
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess)) {
|
||||
while (await reader.ReadAsync()) {
|
||||
Console.Write("{0}: ", reader.GetInt32(0));
|
||||
|
@ -175,8 +158,8 @@ namespace StreamingFromServer {
|
|||
int charsRead = 0;
|
||||
using (TextReader data = reader.GetTextReader(1)) {
|
||||
do {
|
||||
// Grab each chunk of text and write it to the console
|
||||
// If you are writing to a TextWriter you should use WriteAsync or WriteLineAsync
|
||||
// Grab each chunk of text and write it to the console.
|
||||
// If you are writing to a TextWriter, you should use WriteAsync or WriteLineAsync.
|
||||
charsRead = await data.ReadAsync(buffer, 0, buffer.Length);
|
||||
Console.Write(buffer, 0, charsRead);
|
||||
} while (charsRead > 0);
|
||||
|
@ -190,14 +173,14 @@ namespace StreamingFromServer {
|
|||
}
|
||||
}
|
||||
|
||||
// Application transferring a large Xml Document from SQL Server in .NET Framework 4.5
|
||||
// Transfer a large Xml Document from SQL Server in .NET Framework 4.5.
|
||||
private static async Task PrintXmlValues() {
|
||||
using (SqlConnection connection = new SqlConnection(connectionString)) {
|
||||
await connection.OpenAsync();
|
||||
using (SqlCommand command = new SqlCommand("SELECT [id], [xmldata] FROM [Streams]", connection)) {
|
||||
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
|
||||
// Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming.
|
||||
// Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions.
|
||||
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess)) {
|
||||
while (await reader.ReadAsync()) {
|
||||
Console.WriteLine("{0}: ", reader.GetInt32(0));
|
||||
|
@ -208,8 +191,8 @@ namespace StreamingFromServer {
|
|||
else {
|
||||
using (XmlReader xmlReader = reader.GetXmlReader(1)) {
|
||||
int depth = 1;
|
||||
// NOTE: The XmlReader returned by GetXmlReader does NOT support async operations
|
||||
// See the example below (PrintXmlValuesViaNVarChar) for how to get an XmlReader with asynchronous capabilities
|
||||
// NOTE: The XmlReader returned by GetXmlReader does NOT support async operations.
|
||||
// See the example below (PrintXmlValuesViaNVarChar) for how to get an XmlReader with asynchronous capabilities.
|
||||
while (xmlReader.Read()) {
|
||||
switch (xmlReader.NodeType) {
|
||||
case XmlNodeType.Element:
|
||||
|
@ -233,26 +216,26 @@ namespace StreamingFromServer {
|
|||
}
|
||||
}
|
||||
|
||||
// Application transferring a large Xml Document from SQL Server in .NET Framework 4.5
|
||||
// This goes via NVarChar and TextReader to enable asynchronous reading
|
||||
// Transfer a large Xml Document from SQL Server in .NET Framework 4.5.
|
||||
// This goes via NVarChar and TextReader to enable asynchronous reading.
|
||||
private static async Task PrintXmlValuesViaNVarChar() {
|
||||
XmlReaderSettings xmlSettings = new XmlReaderSettings() {
|
||||
// Async must be explicitly enabled in the XmlReaderSettings otherwise the XmlReader will throw exceptions when async methods are called
|
||||
// Async must be explicitly enabled in the XmlReaderSettings otherwise the XmlReader will throw exceptions when async methods are called.
|
||||
Async = true,
|
||||
// Since we will immediately wrap the TextReader we are creating in an XmlReader, we will permit the XmlReader to take care of closing\disposing it
|
||||
// Since we will immediately wrap the TextReader we are creating in an XmlReader, we will permit the XmlReader to take care of closing\disposing it.
|
||||
CloseInput = true,
|
||||
// If the Xml you are reading is not a valid document (as per <https://learn.microsoft.com/previous-versions/dotnet/netframework-4.0/6bts1x50(v=vs.100)>) you will need to set the conformance level to Fragment
|
||||
// If the Xml you are reading is not a valid document (as per <https://learn.microsoft.com/previous-versions/dotnet/netframework-4.0/6bts1x50(v=vs.100)>) you will need to set the conformance level to Fragment.
|
||||
ConformanceLevel = ConformanceLevel.Fragment
|
||||
};
|
||||
|
||||
using (SqlConnection connection = new SqlConnection(connectionString)) {
|
||||
await connection.OpenAsync();
|
||||
|
||||
// Cast the XML into NVarChar to enable GetTextReader - trying to use GetTextReader on an XML type will throw an exception
|
||||
// Cast the XML into NVarChar to enable GetTextReader - trying to use GetTextReader on an XML type will throw an exception.
|
||||
using (SqlCommand command = new SqlCommand("SELECT [id], CAST([xmldata] AS NVARCHAR(MAX)) FROM [Streams]", connection)) {
|
||||
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
|
||||
// Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming.
|
||||
// Otherwise ReadAsync will buffer the entire Xml Document into memory which can cause scalability issues or even OutOfMemoryExceptions.
|
||||
using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess)) {
|
||||
while (await reader.ReadAsync()) {
|
||||
Console.WriteLine("{0}:", reader.GetInt32(0));
|
||||
|
@ -261,11 +244,11 @@ namespace StreamingFromServer {
|
|||
Console.WriteLine("\t(NULL)");
|
||||
}
|
||||
else {
|
||||
// Grab the row as a TextReader, then create an XmlReader on top of it
|
||||
// We are not keeping a reference to the TextReader since the XmlReader is created with the "CloseInput" setting (so it will close the TextReader when needed)
|
||||
// Grab the row as a TextReader, then create an XmlReader on top of it.
|
||||
// The code doesn't keep a reference to the TextReader since the XmlReader is created with the "CloseInput" setting (so it will close the TextReader when needed).
|
||||
using (XmlReader xmlReader = XmlReader.Create(reader.GetTextReader(1), xmlSettings)) {
|
||||
int depth = 1;
|
||||
// The XmlReader above now supports asynchronous operations, so we can use ReadAsync here
|
||||
// The XmlReader above now supports asynchronous operations, so we can use ReadAsync here.
|
||||
while (await xmlReader.ReadAsync()) {
|
||||
switch (xmlReader.NodeType) {
|
||||
case XmlNodeType.Element:
|
||||
|
@ -273,8 +256,8 @@ namespace StreamingFromServer {
|
|||
depth++;
|
||||
break;
|
||||
case XmlNodeType.Text:
|
||||
// Depending on what your data looks like, you should either use Value or GetValueAsync
|
||||
// Value has less overhead (since it doesn't create a Task), but it may also block if additional data is required
|
||||
// Depending on what your data looks like, you should either use Value or GetValueAsync.
|
||||
// Value has less overhead (since it doesn't create a Task), but it may also block if additional data is required.
|
||||
Console.WriteLine("{0}{1}", new string('\t', depth), await xmlReader.GetValueAsync());
|
||||
break;
|
||||
case XmlNodeType.EndElement:
|
||||
|
@ -294,7 +277,7 @@ namespace StreamingFromServer {
|
|||
}
|
||||
```
|
||||
|
||||
## Sample -- Streaming to SQL Server
|
||||
## Sample: Streaming to SQL Server
|
||||
|
||||
Use the following Transact-SQL to create the sample database:
|
||||
|
||||
|
@ -319,17 +302,12 @@ GO
|
|||
|
||||
The sample shows how to do the following:
|
||||
|
||||
- Transferring a large BLOB to SQL Server in .NET Framework 4.5.
|
||||
|
||||
- Transferring a large text file to SQL Server in .NET Framework 4.5.
|
||||
|
||||
- Using the new asynchronous feature to transfer a large BLOB.
|
||||
|
||||
- Using the new asynchronous feature and the await keyword to transfer a large BLOB.
|
||||
|
||||
- Cancelling the transfer of a large BLOB.
|
||||
|
||||
- Streaming from one SQL Server to another using the new asynchronous feature.
|
||||
- Transfer a large BLOB to SQL Server in .NET Framework 4.5.
|
||||
- Transfer a large text file to SQL Server in .NET Framework 4.5.
|
||||
- Use the new asynchronous feature to transfer a large BLOB.
|
||||
- Use the new asynchronous feature and the await keyword to transfer a large BLOB.
|
||||
- Cancel the transfer of a large BLOB.
|
||||
- Stream from one SQL Server to another using the new asynchronous feature.
|
||||
|
||||
```csharp
|
||||
using System;
|
||||
|
@ -341,8 +319,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace StreamingToServer {
|
||||
class Program {
|
||||
// Replace the connection string if needed, for instance to connect to SQL Express: @"Server=(local)\SQLEXPRESS;Database=Demo2;Integrated Security=true"
|
||||
private const string connectionString = @"Server=(localdb)\V11.0;Database=Demo2";
|
||||
private const string connectionString = @"...";
|
||||
|
||||
static void Main(string[] args) {
|
||||
CreateDemoFiles();
|
||||
|
@ -351,23 +328,23 @@ namespace StreamingToServer {
|
|||
StreamTextToServer().Wait();
|
||||
|
||||
// Create a CancellationTokenSource that will be cancelled after 100ms
|
||||
// Typically this token source will be cancelled by a user request (e.g. a Cancel button)
|
||||
// Typically this token source will be cancelled by a user request (e.g. a Cancel button).
|
||||
CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||
tokenSource.CancelAfter(100);
|
||||
try {
|
||||
CancelBLOBStream(tokenSource.Token).Wait();
|
||||
}
|
||||
catch (AggregateException ex) {
|
||||
// Cancelling an async operation will throw an exception
|
||||
// Since we are using the Task's Wait method, this exception will be wrapped in an AggregateException
|
||||
// If you were using the 'await' keyword, the compiler would take care of unwrapping the AggregateException
|
||||
// Depending on when the cancellation occurs, you can either get an error from SQL Server or from .Net
|
||||
// Cancelling an async operation will throw an exception.
|
||||
// Since we are using the Task's Wait method, this exception will be wrapped in an AggregateException.
|
||||
// If you were using the 'await' keyword, the compiler would take care of unwrapping the AggregateException.
|
||||
// Depending on when the cancellation occurs, you can either get an error from SQL Server or from .Net.
|
||||
if ((ex.InnerException is SqlException) || (ex.InnerException is TaskCanceledException)) {
|
||||
// This is an expected exception
|
||||
// This is an expected exception.
|
||||
Console.WriteLine("Got expected exception: {0}", ex.InnerException.Message);
|
||||
}
|
||||
else {
|
||||
// Did not expect this exception - re-throw it
|
||||
// Did not expect this exception - rethrow it.
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +352,7 @@ namespace StreamingToServer {
|
|||
Console.WriteLine("Done");
|
||||
}
|
||||
|
||||
// This is used to generate the files which are used by the other sample methods
|
||||
// This is used to generate the files which are used by the other sample methods.
|
||||
private static void CreateDemoFiles() {
|
||||
Random rand = new Random();
|
||||
byte[] data = new byte[1024];
|
||||
|
@ -390,7 +367,7 @@ namespace StreamingToServer {
|
|||
}
|
||||
}
|
||||
|
||||
// Application transferring a large BLOB to SQL Server in .NET Framework 4.5
|
||||
// Transfer a large BLOB to SQL Server in .NET Framework 4.5.
|
||||
private static async Task StreamBLOBToServer() {
|
||||
using (SqlConnection conn = new SqlConnection(connectionString)) {
|
||||
await conn.OpenAsync();
|
||||
|
@ -398,50 +375,50 @@ namespace StreamingToServer {
|
|||
using (FileStream file = File.Open("binarydata.bin", FileMode.Open)) {
|
||||
|
||||
// Add a parameter which uses the FileStream we just opened
|
||||
// Size is set to -1 to indicate "MAX"
|
||||
// Size is set to -1 to indicate "MAX".
|
||||
cmd.Parameters.Add("@bindata", SqlDbType.Binary, -1).Value = file;
|
||||
|
||||
// Send the data to the server asynchronously
|
||||
// Send the data to the server asynchronously.
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Application transferring a large Text File to SQL Server in .NET Framework 4.5
|
||||
// Transfer a large Text File to SQL Server in .NET Framework 4.5.
|
||||
private static async Task StreamTextToServer() {
|
||||
using (SqlConnection conn = new SqlConnection(connectionString)) {
|
||||
await conn.OpenAsync();
|
||||
using (SqlCommand cmd = new SqlCommand("INSERT INTO [TextStreams] (textdata) VALUES (@textdata)", conn)) {
|
||||
using (StreamReader file = File.OpenText("textdata.txt")) {
|
||||
|
||||
// Add a parameter which uses the StreamReader we just opened
|
||||
// Size is set to -1 to indicate "MAX"
|
||||
// Add a parameter which uses the StreamReader we just opened.
|
||||
// Size is set to -1 to indicate "MAX".
|
||||
cmd.Parameters.Add("@textdata", SqlDbType.NVarChar, -1).Value = file;
|
||||
|
||||
// Send the data to the server asynchronously
|
||||
// Send the data to the server asynchronously.
|
||||
await cmd.ExecuteNonQueryAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cancelling the transfer of a large BLOB
|
||||
// Cancel the transfer of a large BLOB.
|
||||
private static async Task CancelBLOBStream(CancellationToken cancellationToken) {
|
||||
using (SqlConnection conn = new SqlConnection(connectionString)) {
|
||||
// We can cancel not only sending the data to the server, but also opening the connection
|
||||
// We can cancel not only sending the data to the server, but also opening the connection.
|
||||
await conn.OpenAsync(cancellationToken);
|
||||
|
||||
// Artificially delay the command by 100ms
|
||||
// Artificially delay the command by 100ms.
|
||||
using (SqlCommand cmd = new SqlCommand("WAITFOR DELAY '00:00:00:100';INSERT INTO [BinaryStreams] (bindata) VALUES (@bindata)", conn)) {
|
||||
using (FileStream file = File.Open("binarydata.bin", FileMode.Open)) {
|
||||
|
||||
// Add a parameter which uses the FileStream we just opened
|
||||
// Size is set to -1 to indicate "MAX"
|
||||
// Add a parameter which uses the FileStream we just opened.
|
||||
// Size is set to -1 to indicate "MAX".
|
||||
cmd.Parameters.Add("@bindata", SqlDbType.Binary, -1).Value = file;
|
||||
|
||||
// Send the data to the server asynchronously
|
||||
// Pass the cancellation token such that the command will be cancelled if needed
|
||||
// Send the data to the server asynchronously.
|
||||
// Pass the cancellation token such that the command will be cancelled if needed.
|
||||
await cmd.ExecuteNonQueryAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +428,7 @@ namespace StreamingToServer {
|
|||
}
|
||||
```
|
||||
|
||||
## Sample -- Streaming From One SQL Server to Another SQL Server
|
||||
## Sample: Streaming From One SQL Server to Another SQL Server
|
||||
|
||||
This sample demonstrates how to asynchronously stream a large BLOB from one SQL Server to another, with support for cancellation.
|
||||
|
||||
|
@ -465,24 +442,23 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace StreamingFromServerToAnother {
|
||||
class Program {
|
||||
// Replace the connection string if needed, for instance to connect to SQL Express: @"Server=(local)\SQLEXPRESS;Database=Demo2;Integrated Security=true"
|
||||
private const string connectionString = @"Server=(localdb)\V11.0;Database=Demo2";
|
||||
private const string connectionString = @"...";
|
||||
|
||||
static void Main(string[] args) {
|
||||
// For this example, we don't want to cancel
|
||||
// So we can pass in a "blank" cancellation token
|
||||
// For this example, we don't want to cancel,
|
||||
// so pass in a "blank" cancellation token.
|
||||
E2EStream(CancellationToken.None).Wait();
|
||||
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
|
||||
// Streaming from one SQL Server to Another One using the new Async.NET
|
||||
// Streaming from one SQL Server to Another One using the new Async.NET.
|
||||
private static async Task E2EStream(CancellationToken cancellationToken) {
|
||||
using (SqlConnection readConn = new SqlConnection(connectionString)) {
|
||||
using (SqlConnection writeConn = new SqlConnection(connectionString)) {
|
||||
|
||||
// Note that we are using the same cancellation token for calls to both connections\commands
|
||||
// Also we can start both the connection opening asynchronously, and then wait for both to complete
|
||||
// Note that we are using the same cancellation token for calls to both connections\commands.
|
||||
// Also we can start both the connection opening asynchronously, and then wait for both to complete.
|
||||
Task openReadConn = readConn.OpenAsync(cancellationToken);
|
||||
Task openWriteConn = writeConn.OpenAsync(cancellationToken);
|
||||
await Task.WhenAll(openReadConn, openWriteConn);
|
||||
|
@ -490,21 +466,21 @@ namespace StreamingFromServerToAnother {
|
|||
using (SqlCommand readCmd = new SqlCommand("SELECT [bindata] FROM [BinaryStreams]", readConn)) {
|
||||
using (SqlCommand writeCmd = new SqlCommand("INSERT INTO [BinaryStreamsCopy] (bindata) VALUES (@bindata)", writeConn)) {
|
||||
|
||||
// Add an empty parameter to the write command which will be used for the streams we are copying
|
||||
// Size is set to -1 to indicate "MAX"
|
||||
// Add an empty parameter to the write command which will be used for the streams we are copying.
|
||||
// Size is set to -1 to indicate "MAX".
|
||||
SqlParameter streamParameter = writeCmd.Parameters.Add("@bindata", SqlDbType.Binary, -1);
|
||||
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming
|
||||
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions
|
||||
// The reader needs to be executed with the SequentialAccess behavior to enable network streaming.
|
||||
// Otherwise ReadAsync will buffer the entire BLOB into memory which can cause scalability issues or even OutOfMemoryExceptions.
|
||||
using (SqlDataReader reader = await readCmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess, cancellationToken)) {
|
||||
while (await reader.ReadAsync(cancellationToken)) {
|
||||
// Grab a stream to the binary data in the source database
|
||||
// Grab a stream to the binary data in the source database.
|
||||
using (Stream dataStream = reader.GetStream(0)) {
|
||||
|
||||
// Set the parameter value to the stream source that was opened
|
||||
// Set the parameter value to the stream source that was opened.
|
||||
streamParameter.Value = dataStream;
|
||||
|
||||
// Asynchronously send data from one database to another
|
||||
// Asynchronously send data from one database to another.
|
||||
await writeCmd.ExecuteNonQueryAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,234 +1,233 @@
|
|||
---
|
||||
description: "Learn more about: System.Transactions Integration with SQL Server"
|
||||
description: "Learn more about System.Transactions integration with SQL Server, which exposes transactions in a way that is fully integrated in .NET Framework."
|
||||
title: "System.Transactions Integration with SQL Server"
|
||||
ms.date: "03/30/2017"
|
||||
dev_langs:
|
||||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: b555544e-7abb-4814-859b-ab9cdd7d8716
|
||||
---
|
||||
# System.Transactions Integration with SQL Server
|
||||
# System.Transactions integration with SQL Server
|
||||
|
||||
The .NET Framework version 2.0 introduced a transaction framework that can be accessed through the <xref:System.Transactions> namespace. This framework exposes transactions in a way that is fully integrated in the .NET Framework, including ADO.NET.
|
||||
|
||||
In addition to the programmability enhancements, <xref:System.Transactions> and ADO.NET can work together to coordinate optimizations when you work with transactions. A promotable transaction is a lightweight (local) transaction that can be automatically promoted to a fully distributed transaction on an as-needed basis.
|
||||
|
||||
Starting with ADO.NET 2.0, <xref:System.Data.SqlClient> supports promotable transactions when you work with SQL Server. A promotable transaction does not invoke the added overhead of a distributed transaction unless the added overhead is required. Promotable transactions are automatic and require no intervention from the developer.
|
||||
|
||||
Promotable transactions are only available when you use the .NET Framework Data Provider for SQL Server (`SqlClient`) with SQL Server.
|
||||
|
||||
## Creating Promotable Transactions
|
||||
.NET Framework version 2.0 introduced a transaction framework that can be accessed through the <xref:System.Transactions> namespace. This framework exposes transactions in a way that is fully integrated in .NET Framework, including ADO.NET.
|
||||
|
||||
In addition to the programmability enhancements, <xref:System.Transactions> and ADO.NET can work together to coordinate optimizations when you work with transactions. A promotable transaction is a lightweight (local) transaction that can be automatically promoted to a fully distributed transaction on an as-needed basis.
|
||||
|
||||
Starting with ADO.NET 2.0, <xref:System.Data.SqlClient> supports promotable transactions when you work with SQL Server. A promotable transaction does not invoke the added overhead of a distributed transaction unless the added overhead is required. Promotable transactions are automatic and require no intervention from the developer.
|
||||
|
||||
Promotable transactions are only available when you use the .NET Framework Data Provider for SQL Server (`SqlClient`) with SQL Server.
|
||||
|
||||
## Creating Promotable Transactions
|
||||
|
||||
The .NET Framework Provider for SQL Server provides support for promotable transactions, which are handled through the classes in the .NET Framework <xref:System.Transactions> namespace. Promotable transactions optimize distributed transactions by deferring creating a distributed transaction until it is needed. If only one resource manager is required, no distributed transaction occurs.
|
||||
|
||||
The .NET Framework Provider for SQL Server provides support for promotable transactions, which are handled through the classes in the .NET Framework <xref:System.Transactions> namespace. Promotable transactions optimize distributed transactions by deferring creating a distributed transaction until it is needed. If only one resource manager is required, no distributed transaction occurs.
|
||||
|
||||
> [!NOTE]
|
||||
> In a partially trusted scenario, the <xref:System.Transactions.DistributedTransactionPermission> is required when a transaction is promoted to a distributed transaction.
|
||||
|
||||
## Promotable Transaction Scenarios
|
||||
> In a partially trusted scenario, the <xref:System.Transactions.DistributedTransactionPermission> is required when a transaction is promoted to a distributed transaction.
|
||||
|
||||
Distributed transactions typically consume significant system resources, being managed by Microsoft Distributed Transaction Coordinator (MS DTC), which integrates all the resource managers accessed in the transaction. A promotable transaction is a special form of a <xref:System.Transactions> transaction that effectively delegates the work to a simple SQL Server transaction. <xref:System.Transactions>, <xref:System.Data.SqlClient>, and SQL Server coordinate the work involved in handling the transaction, promoting it to a full distributed transaction as needed.
|
||||
|
||||
The benefit of using promotable transactions is that when a connection is opened by using an active <xref:System.Transactions.TransactionScope> transaction, and no other connections are opened, the transaction commits as a lightweight transaction, instead of incurring the additional overhead of a full distributed transaction.
|
||||
|
||||
### Connection String Keywords
|
||||
## Promotable Transaction Scenarios
|
||||
|
||||
The <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A> property supports a keyword, `Enlist`, which indicates whether <xref:System.Data.SqlClient> will detect transactional contexts and automatically enlist the connection in a distributed transaction. If `Enlist=true`, the connection is automatically enlisted in the opening thread's current transaction context. If `Enlist=false`, the `SqlClient` connection does not interact with a distributed transaction. The default value for `Enlist` is true. If `Enlist` is not specified in the connection string, the connection is automatically enlisted in a distributed transaction if one is detected when the connection is opened.
|
||||
|
||||
The `Transaction Binding` keywords in a <xref:System.Data.SqlClient.SqlConnection> connection string control the connection's association with an enlisted `System.Transactions` transaction. It is also available through the <xref:System.Data.SqlClient.SqlConnectionStringBuilder.TransactionBinding%2A> property of a <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
|
||||
The following table describes the possible values.
|
||||
|
||||
|Keyword|Description|
|
||||
|-------------|-----------------|
|
||||
|Implicit Unbind|The default. The connection detaches from the transaction when it ends, switching back to autocommit mode.|
|
||||
|Explicit Unbind|The connection remains attached to the transaction until the transaction is closed. The connection will fail if the associated transaction is not active or does not match <xref:System.Transactions.Transaction.Current%2A>.|
|
||||
|
||||
## Using TransactionScope
|
||||
Distributed transactions typically consume significant system resources, being managed by Microsoft Distributed Transaction Coordinator (MS DTC), which integrates all the resource managers accessed in the transaction. A promotable transaction is a special form of a <xref:System.Transactions> transaction that effectively delegates the work to a simple SQL Server transaction. <xref:System.Transactions>, <xref:System.Data.SqlClient>, and SQL Server coordinate the work involved in handling the transaction, promoting it to a full distributed transaction as needed.
|
||||
|
||||
The benefit of using promotable transactions is that when a connection is opened by using an active <xref:System.Transactions.TransactionScope> transaction, and no other connections are opened, the transaction commits as a lightweight transaction, instead of incurring the additional overhead of a full distributed transaction.
|
||||
|
||||
### Connection String Keywords
|
||||
|
||||
The <xref:System.Data.SqlClient.SqlConnection.ConnectionString> property supports a keyword, `Enlist`, which indicates whether <xref:System.Data.SqlClient> will detect transactional contexts and automatically enlist the connection in a distributed transaction. If `Enlist=true`, the connection is automatically enlisted in the opening thread's current transaction context. If `Enlist=false`, the `SqlClient` connection does not interact with a distributed transaction. The default value for `Enlist` is true. If `Enlist` is not specified in the connection string, the connection is automatically enlisted in a distributed transaction if one is detected when the connection is opened.
|
||||
|
||||
The `Transaction Binding` keywords in a <xref:System.Data.SqlClient.SqlConnection> connection string control the connection's association with an enlisted `System.Transactions` transaction. It is also available through the <xref:System.Data.SqlClient.SqlConnectionStringBuilder.TransactionBinding> property of a <xref:System.Data.SqlClient.SqlConnectionStringBuilder>.
|
||||
|
||||
The following table describes the possible values.
|
||||
|
||||
|Keyword|Description|
|
||||
|-------------|-----------------|
|
||||
|Implicit Unbind|The default. The connection detaches from the transaction when it ends, switching back to autocommit mode.|
|
||||
|Explicit Unbind|The connection remains attached to the transaction until the transaction is closed. The connection will fail if the associated transaction is not active or does not match <xref:System.Transactions.Transaction.Current%2A>.|
|
||||
|
||||
## Using TransactionScope
|
||||
|
||||
The <xref:System.Transactions.TransactionScope> class makes a code block transactional by implicitly enlisting connections in a distributed transaction. You must call the <xref:System.Transactions.TransactionScope.Complete%2A> method at the end of the <xref:System.Transactions.TransactionScope> block before leaving it. Leaving the block invokes the <xref:System.Transactions.TransactionScope.Dispose%2A> method. If an exception has been thrown that causes the code to leave scope, the transaction is considered aborted.
|
||||
|
||||
We recommend that you use a `using` block to make sure that <xref:System.Transactions.TransactionScope.Dispose%2A> is called on the <xref:System.Transactions.TransactionScope> object when the using block is exited. Failure to commit or roll back pending transactions can significantly damage performance because the default time-out for the <xref:System.Transactions.TransactionScope> is one minute. If you do not use a `using` statement, you must perform all work in a `Try` block and explicitly call the <xref:System.Transactions.TransactionScope.Dispose%2A> method in the `Finally` block.
|
||||
|
||||
If an exception occurs in the <xref:System.Transactions.TransactionScope>, the transaction is marked as inconsistent and is abandoned. It will be rolled back when the <xref:System.Transactions.TransactionScope> is disposed. If no exception occurs, participating transactions commit.
|
||||
|
||||
The <xref:System.Transactions.TransactionScope> class makes a code block transactional by implicitly enlisting connections in a distributed transaction. You must call the <xref:System.Transactions.TransactionScope.Complete%2A> method at the end of the <xref:System.Transactions.TransactionScope> block before leaving it. Leaving the block invokes the <xref:System.Transactions.TransactionScope.Dispose%2A> method. If an exception has been thrown that causes the code to leave scope, the transaction is considered aborted.
|
||||
|
||||
We recommend that you use a `using` block to make sure that <xref:System.Transactions.TransactionScope.Dispose%2A> is called on the <xref:System.Transactions.TransactionScope> object when the using block is exited. Failure to commit or roll back pending transactions can significantly damage performance because the default time-out for the <xref:System.Transactions.TransactionScope> is one minute. If you do not use a `using` statement, you must perform all work in a `Try` block and explicitly call the <xref:System.Transactions.TransactionScope.Dispose%2A> method in the `Finally` block.
|
||||
|
||||
If an exception occurs in the <xref:System.Transactions.TransactionScope>, the transaction is marked as inconsistent and is abandoned. It will be rolled back when the <xref:System.Transactions.TransactionScope> is disposed. If no exception occurs, participating transactions commit.
|
||||
|
||||
> [!NOTE]
|
||||
> The `TransactionScope` class creates a transaction with a <xref:System.Transactions.Transaction.IsolationLevel%2A> of `Serializable` by default. Depending on your application, you might want to consider lowering the isolation level to avoid high contention in your application.
|
||||
|
||||
> [!NOTE]
|
||||
> We recommend that you perform only updates, inserts, and deletes within distributed transactions because they consume significant database resources. Select statements may lock database resources unnecessarily, and in some scenarios, you may have to use transactions for selects. Any non-database work should be done outside the scope of the transaction, unless it involves other transacted resource managers. Although an exception in the scope of the transaction prevents the transaction from committing, the <xref:System.Transactions.TransactionScope> class has no provision for rolling back any changes your code has made outside the scope of the transaction itself. If you have to take some action when the transaction is rolled back, you must write your own implementation of the <xref:System.Transactions.IEnlistmentNotification> interface and explicitly enlist in the transaction.
|
||||
|
||||
## Example
|
||||
> The `TransactionScope` class creates a transaction with a <xref:System.Transactions.Transaction.IsolationLevel%2A> of `Serializable` by default. Depending on your application, you might want to consider lowering the isolation level to avoid high contention in your application.
|
||||
|
||||
Working with <xref:System.Transactions> requires that you have a reference to System.Transactions.dll.
|
||||
|
||||
The following function demonstrates how to create a promotable transaction against two different SQL Server instances, represented by two different <xref:System.Data.SqlClient.SqlConnection> objects, which are wrapped in a <xref:System.Transactions.TransactionScope> block. The code creates the <xref:System.Transactions.TransactionScope> block with a `using` statement and opens the first connection, which automatically enlists it in the <xref:System.Transactions.TransactionScope>. The transaction is initially enlisted as a lightweight transaction, not a full distributed transaction. The second connection is enlisted in the <xref:System.Transactions.TransactionScope> only if the command in the first connection does not throw an exception. When the second connection is opened, the transaction is automatically promoted to a full distributed transaction. The <xref:System.Transactions.TransactionScope.Complete%2A> method is invoked, which commits the transaction only if no exceptions have been thrown. If an exception has been thrown at any point in the <xref:System.Transactions.TransactionScope> block, `Complete` will not be called, and the distributed transaction will roll back when the <xref:System.Transactions.TransactionScope> is disposed at the end of its `using` block.
|
||||
|
||||
```csharp
|
||||
// This function takes arguments for the 2 connection strings and commands in order
|
||||
// to create a transaction involving two SQL Servers. It returns a value > 0 if the
|
||||
> [!NOTE]
|
||||
> We recommend that you perform only updates, inserts, and deletes within distributed transactions because they consume significant database resources. Select statements may lock database resources unnecessarily, and in some scenarios, you may have to use transactions for selects. Any non-database work should be done outside the scope of the transaction, unless it involves other transacted resource managers. Although an exception in the scope of the transaction prevents the transaction from committing, the <xref:System.Transactions.TransactionScope> class has no provision for rolling back any changes your code has made outside the scope of the transaction itself. If you have to take some action when the transaction is rolled back, you must write your own implementation of the <xref:System.Transactions.IEnlistmentNotification> interface and explicitly enlist in the transaction.
|
||||
|
||||
## Example
|
||||
|
||||
Working with <xref:System.Transactions> requires that you have a reference to System.Transactions.dll.
|
||||
|
||||
The following function demonstrates how to create a promotable transaction against two different SQL Server instances, represented by two different <xref:System.Data.SqlClient.SqlConnection> objects, which are wrapped in a <xref:System.Transactions.TransactionScope> block. The code creates the <xref:System.Transactions.TransactionScope> block with a `using` statement and opens the first connection, which automatically enlists it in the <xref:System.Transactions.TransactionScope>. The transaction is initially enlisted as a lightweight transaction, not a full distributed transaction. The second connection is enlisted in the <xref:System.Transactions.TransactionScope> only if the command in the first connection does not throw an exception. When the second connection is opened, the transaction is automatically promoted to a full distributed transaction. The <xref:System.Transactions.TransactionScope.Complete%2A> method is invoked, which commits the transaction only if no exceptions have been thrown. If an exception has been thrown at any point in the <xref:System.Transactions.TransactionScope> block, `Complete` will not be called, and the distributed transaction will roll back when the <xref:System.Transactions.TransactionScope> is disposed at the end of its `using` block.
|
||||
|
||||
```csharp
|
||||
// This function takes arguments for the 2 connection strings and commands in order
|
||||
// to create a transaction involving two SQL Servers. It returns a value > 0 if the
|
||||
// transaction committed, 0 if the transaction rolled back. To test this code, you can
|
||||
// connect to two different databases on the same server by altering the connection string,
|
||||
// or to another RDBMS such as Oracle by altering the code in the connection2 code block.
|
||||
static public int CreateTransactionScope(
|
||||
string connectString1, string connectString2,
|
||||
string commandText1, string commandText2)
|
||||
{
|
||||
// Initialize the return value to zero and create a StringWriter to display results.
|
||||
int returnValue = 0;
|
||||
System.IO.StringWriter writer = new System.IO.StringWriter();
|
||||
|
||||
// Create the TransactionScope in which to execute the commands, guaranteeing
|
||||
// that both commands will commit or roll back as a single unit of work.
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
{
|
||||
using (SqlConnection connection1 = new SqlConnection(connectString1))
|
||||
{
|
||||
try
|
||||
{
|
||||
// connect to two different databases on the same server by altering the connection string,
|
||||
// or to another RDBMS such as Oracle by altering the code in the connection2 code block.
|
||||
static public int CreateTransactionScope(
|
||||
string connectString1, string connectString2,
|
||||
string commandText1, string commandText2)
|
||||
{
|
||||
// Initialize the return value to zero and create a StringWriter to display results.
|
||||
int returnValue = 0;
|
||||
System.IO.StringWriter writer = new System.IO.StringWriter();
|
||||
|
||||
// Create the TransactionScope in which to execute the commands, guaranteeing
|
||||
// that both commands will commit or roll back as a single unit of work.
|
||||
using (TransactionScope scope = new TransactionScope())
|
||||
{
|
||||
using (SqlConnection connection1 = new SqlConnection(connectString1))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Opening the connection automatically enlists it in the
|
||||
// TransactionScope as a lightweight transaction.
|
||||
connection1.Open();
|
||||
|
||||
// Create the SqlCommand object and execute the first command.
|
||||
SqlCommand command1 = new SqlCommand(commandText1, connection1);
|
||||
returnValue = command1.ExecuteNonQuery();
|
||||
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
|
||||
|
||||
// if you get here, this means that command1 succeeded. By nesting
|
||||
// the using block for connection2 inside that of connection1, you
|
||||
// TransactionScope as a lightweight transaction.
|
||||
connection1.Open();
|
||||
|
||||
// Create the SqlCommand object and execute the first command.
|
||||
SqlCommand command1 = new SqlCommand(commandText1, connection1);
|
||||
returnValue = command1.ExecuteNonQuery();
|
||||
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
|
||||
|
||||
// if you get here, this means that command1 succeeded. By nesting
|
||||
// the using block for connection2 inside that of connection1, you
|
||||
// conserve server and network resources by opening connection2
|
||||
// only when there is a chance that the transaction can commit.
|
||||
using (SqlConnection connection2 = new SqlConnection(connectString2))
|
||||
try
|
||||
{
|
||||
// The transaction is promoted to a full distributed
|
||||
// transaction when connection2 is opened.
|
||||
connection2.Open();
|
||||
|
||||
// Execute the second command in the second database.
|
||||
returnValue = 0;
|
||||
SqlCommand command2 = new SqlCommand(commandText2, connection2);
|
||||
returnValue = command2.ExecuteNonQuery();
|
||||
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Display information that command2 failed.
|
||||
writer.WriteLine("returnValue for command2: {0}", returnValue);
|
||||
writer.WriteLine("Exception Message2: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Display information that command1 failed.
|
||||
writer.WriteLine("returnValue for command1: {0}", returnValue);
|
||||
writer.WriteLine("Exception Message1: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
using (SqlConnection connection2 = new SqlConnection(connectString2))
|
||||
try
|
||||
{
|
||||
// The transaction is promoted to a full distributed
|
||||
// transaction when connection2 is opened.
|
||||
connection2.Open();
|
||||
|
||||
// Execute the second command in the second database.
|
||||
returnValue = 0;
|
||||
SqlCommand command2 = new SqlCommand(commandText2, connection2);
|
||||
returnValue = command2.ExecuteNonQuery();
|
||||
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Display information that command2 failed.
|
||||
writer.WriteLine("returnValue for command2: {0}", returnValue);
|
||||
writer.WriteLine("Exception Message2: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Display information that command1 failed.
|
||||
writer.WriteLine("returnValue for command1: {0}", returnValue);
|
||||
writer.WriteLine("Exception Message1: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
// If an exception has been thrown, Complete will not
|
||||
// be called and the transaction is rolled back.
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
// The returnValue is greater than 0 if the transaction committed.
|
||||
if (returnValue > 0)
|
||||
{
|
||||
writer.WriteLine("Transaction was committed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// You could write additional business logic here, notify the caller by
|
||||
// throwing a TransactionAbortedException, or log the failure.
|
||||
writer.WriteLine("Transaction rolled back.");
|
||||
}
|
||||
|
||||
// Display messages.
|
||||
Console.WriteLine(writer.ToString());
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
```
|
||||
|
||||
```vb
|
||||
' This function takes arguments for the 2 connection strings and commands in order
|
||||
' to create a transaction involving two SQL Servers. It returns a value > 0 if the
|
||||
// be called and the transaction is rolled back.
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
// The returnValue is greater than 0 if the transaction committed.
|
||||
if (returnValue > 0)
|
||||
{
|
||||
writer.WriteLine("Transaction was committed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// You could write additional business logic here, notify the caller by
|
||||
// throwing a TransactionAbortedException, or log the failure.
|
||||
writer.WriteLine("Transaction rolled back.");
|
||||
}
|
||||
|
||||
// Display messages.
|
||||
Console.WriteLine(writer.ToString());
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
```
|
||||
|
||||
```vb
|
||||
' This function takes arguments for the 2 connection strings and commands in order
|
||||
' to create a transaction involving two SQL Servers. It returns a value > 0 if the
|
||||
' transaction committed, 0 if the transaction rolled back. To test this code, you can
|
||||
' connect to two different databases on the same server by altering the connection string,
|
||||
' or to another RDBMS such as Oracle by altering the code in the connection2 code block.
|
||||
Public Function CreateTransactionScope( _
|
||||
ByVal connectString1 As String, ByVal connectString2 As String, _
|
||||
ByVal commandText1 As String, ByVal commandText2 As String) As Integer
|
||||
|
||||
' Initialize the return value to zero and create a StringWriter to display results.
|
||||
Dim returnValue As Integer = 0
|
||||
Dim writer As System.IO.StringWriter = New System.IO.StringWriter
|
||||
|
||||
' Create the TransactionScope in which to execute the commands, guaranteeing
|
||||
' that both commands will commit or roll back as a single unit of work.
|
||||
Using scope As New TransactionScope()
|
||||
Using connection1 As New SqlConnection(connectString1)
|
||||
Try
|
||||
' connect to two different databases on the same server by altering the connection string,
|
||||
' or to another RDBMS such as Oracle by altering the code in the connection2 code block.
|
||||
Public Function CreateTransactionScope( _
|
||||
ByVal connectString1 As String, ByVal connectString2 As String, _
|
||||
ByVal commandText1 As String, ByVal commandText2 As String) As Integer
|
||||
|
||||
' Initialize the return value to zero and create a StringWriter to display results.
|
||||
Dim returnValue As Integer = 0
|
||||
Dim writer As System.IO.StringWriter = New System.IO.StringWriter
|
||||
|
||||
' Create the TransactionScope in which to execute the commands, guaranteeing
|
||||
' that both commands will commit or roll back as a single unit of work.
|
||||
Using scope As New TransactionScope()
|
||||
Using connection1 As New SqlConnection(connectString1)
|
||||
Try
|
||||
' Opening the connection automatically enlists it in the
|
||||
' TransactionScope as a lightweight transaction.
|
||||
connection1.Open()
|
||||
|
||||
' Create the SqlCommand object and execute the first command.
|
||||
Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
|
||||
returnValue = command1.ExecuteNonQuery()
|
||||
writer.WriteLine("Rows to be affected by command1: {0}", returnValue)
|
||||
|
||||
' If you get here, this means that command1 succeeded. By nesting
|
||||
' the Using block for connection2 inside that of connection1, you
|
||||
' TransactionScope as a lightweight transaction.
|
||||
connection1.Open()
|
||||
|
||||
' Create the SqlCommand object and execute the first command.
|
||||
Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
|
||||
returnValue = command1.ExecuteNonQuery()
|
||||
writer.WriteLine("Rows to be affected by command1: {0}", returnValue)
|
||||
|
||||
' If you get here, this means that command1 succeeded. By nesting
|
||||
' the Using block for connection2 inside that of connection1, you
|
||||
' conserve server and network resources by opening connection2
|
||||
' only when there is a chance that the transaction can commit.
|
||||
Using connection2 As New SqlConnection(connectString2)
|
||||
Try
|
||||
' The transaction is promoted to a full distributed
|
||||
' transaction when connection2 is opened.
|
||||
connection2.Open()
|
||||
|
||||
' Execute the second command in the second database.
|
||||
returnValue = 0
|
||||
Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
|
||||
returnValue = command2.ExecuteNonQuery()
|
||||
writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
|
||||
|
||||
Catch ex As Exception
|
||||
' Display information that command2 failed.
|
||||
writer.WriteLine("returnValue for command2: {0}", returnValue)
|
||||
writer.WriteLine("Exception Message2: {0}", ex.Message)
|
||||
End Try
|
||||
End Using
|
||||
|
||||
Catch ex As Exception
|
||||
' Display information that command1 failed.
|
||||
writer.WriteLine("returnValue for command1: {0}", returnValue)
|
||||
writer.WriteLine("Exception Message1: {0}", ex.Message)
|
||||
End Try
|
||||
End Using
|
||||
|
||||
Using connection2 As New SqlConnection(connectString2)
|
||||
Try
|
||||
' The transaction is promoted to a full distributed
|
||||
' transaction when connection2 is opened.
|
||||
connection2.Open()
|
||||
|
||||
' Execute the second command in the second database.
|
||||
returnValue = 0
|
||||
Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
|
||||
returnValue = command2.ExecuteNonQuery()
|
||||
writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
|
||||
|
||||
Catch ex As Exception
|
||||
' Display information that command2 failed.
|
||||
writer.WriteLine("returnValue for command2: {0}", returnValue)
|
||||
writer.WriteLine("Exception Message2: {0}", ex.Message)
|
||||
End Try
|
||||
End Using
|
||||
|
||||
Catch ex As Exception
|
||||
' Display information that command1 failed.
|
||||
writer.WriteLine("returnValue for command1: {0}", returnValue)
|
||||
writer.WriteLine("Exception Message1: {0}", ex.Message)
|
||||
End Try
|
||||
End Using
|
||||
|
||||
' If an exception has been thrown, Complete will
|
||||
' not be called and the transaction is rolled back.
|
||||
scope.Complete()
|
||||
End Using
|
||||
|
||||
' The returnValue is greater than 0 if the transaction committed.
|
||||
If returnValue > 0 Then
|
||||
writer.WriteLine("Transaction was committed.")
|
||||
Else
|
||||
' You could write additional business logic here, notify the caller by
|
||||
' throwing a TransactionAbortedException, or log the failure.
|
||||
writer.WriteLine("Transaction rolled back.")
|
||||
End If
|
||||
|
||||
' Display messages.
|
||||
Console.WriteLine(writer.ToString())
|
||||
|
||||
Return returnValue
|
||||
End Function
|
||||
```
|
||||
|
||||
' not be called and the transaction is rolled back.
|
||||
scope.Complete()
|
||||
End Using
|
||||
|
||||
' The returnValue is greater than 0 if the transaction committed.
|
||||
If returnValue > 0 Then
|
||||
writer.WriteLine("Transaction was committed.")
|
||||
Else
|
||||
' You could write additional business logic here, notify the caller by
|
||||
' throwing a TransactionAbortedException, or log the failure.
|
||||
writer.WriteLine("Transaction rolled back.")
|
||||
End If
|
||||
|
||||
' Display messages.
|
||||
Console.WriteLine(writer.ToString())
|
||||
|
||||
Return returnValue
|
||||
End Function
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [Transactions and Concurrency](transactions-and-concurrency.md)
|
||||
|
|
|
@ -5,9 +5,8 @@ ms.date: "03/30/2017"
|
|||
dev_langs:
|
||||
- "csharp"
|
||||
- "vb"
|
||||
ms.assetid: d1bd9a8c-0e29-40e3-bda8-d89176b72fb1
|
||||
---
|
||||
# Updating Data Sources with DataAdapters
|
||||
# Update data sources with DataAdapters
|
||||
|
||||
The `Update` method of the <xref:System.Data.Common.DataAdapter> is called to resolve changes from a <xref:System.Data.DataSet> back to the data source. The `Update` method, like the `Fill` method, takes as arguments an instance of a `DataSet`, and an optional <xref:System.Data.DataTable> object or `DataTable` name. The `DataSet` instance is the `DataSet` that contains the changes that have been made, and the `DataTable` identifies the table from which to retrieve the changes. If no `DataTable` is specified, the first `DataTable` in the `DataSet` is used.
|
||||
|
||||
|
@ -193,7 +192,6 @@ namespace CSDataAdapterOperations.Properties {
|
|||
}
|
||||
|
||||
[global::System.Configuration.ApplicationScopedSettingAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("Data Source=(local);Initial Catalog=MySchool;Integrated Security=True")]
|
||||
public string MySchoolConnectionString {
|
||||
get {
|
||||
return ((string)(this["MySchoolConnectionString"]));
|
||||
|
|
|
@ -6,23 +6,23 @@ ms.topic: whats-new
|
|||
---
|
||||
# What's new in ADO.NET
|
||||
|
||||
The following features are new in ADO.NET in the .NET Framework 4.5.
|
||||
The following features are new in ADO.NET in .NET Framework 4.5.
|
||||
|
||||
## SqlClient Data Provider
|
||||
|
||||
The following features are new in the .NET Framework Data Provider for SQL Server in .NET Framework 4.5:
|
||||
|
||||
- The ConnectRetryCount and ConnectRetryInterval connection string keywords (<xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>) let you control the idle connection resiliency feature.
|
||||
- The `ConnectRetryCount` and `ConnectRetryInterval` connection string keywords (<xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>) let you control the idle connection resiliency feature.
|
||||
|
||||
- Streaming support from SQL Server to an application supports scenarios where data on the server is unstructured. See [SqlClient Streaming Support](sqlclient-streaming-support.md) for more information.
|
||||
- Streaming support from SQL Server to an application supports scenarios where data on the server is unstructured. For more information, see [SqlClient Streaming Support](sqlclient-streaming-support.md).
|
||||
|
||||
- Support has been added for asynchronous programming. See [Asynchronous Programming](asynchronous-programming.md) for more information.
|
||||
- Support has been added for asynchronous programming. For more information, see [Asynchronous Programming](asynchronous-programming.md).
|
||||
|
||||
- Connection failures will now be logged in the extended events log. For more information, see [Data Tracing in ADO.NET](data-tracing.md).
|
||||
|
||||
- SqlClient now has support for SQL Server's high availability, disaster recovery feature, AlwaysOn. For more information, see [SqlClient Support for High Availability, Disaster Recovery](./sql/sqlclient-support-for-high-availability-disaster-recovery.md).
|
||||
|
||||
- A password can be passed as a <xref:System.Security.SecureString> when using SQL Server Authentication. See <xref:System.Data.SqlClient.SqlCredential> for more information.
|
||||
- A password can be passed as a <xref:System.Security.SecureString> when using SQL Server Authentication. For more information, see <xref:System.Data.SqlClient.SqlCredential>.
|
||||
|
||||
- When `TrustServerCertificate` is false and `Encrypt` is true, the server name (or IP address) in a SQL Server SSL certificate must exactly match the server name (or IP address) specified in the connection string. Otherwise, the connection attempt will fail. For more information, see the description of the `Encrypt` connection option in <xref:System.Data.SqlClient.SqlConnection.ConnectionString%2A>.
|
||||
|
||||
|
@ -46,7 +46,7 @@ The following features are new in the .NET Framework Data Provider for SQL Serve
|
|||
|
||||
## ADO.NET Entity Framework
|
||||
|
||||
.NET Framework 4.5 adds APIs that enable new scenarios when working with Entity Framework 5.0. For more information about improvements and features that were added to Entity Framework 5.0, see the following articles: [What’s New](/previous-versions/gg696190(v=vs.103)) and [Entity Framework Releases and Versioning](/ef/ef6/what-is-new/past-releases).
|
||||
.NET Framework 4.5 added APIs that enabled new scenarios when working with Entity Framework 5.0. For more information about improvements and features that were added to Entity Framework 5.0, see [Entity Framework Releases and Versioning](/ef/ef6/what-is-new/past-releases).
|
||||
|
||||
## See also
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ namespace DataViewWinFormsSample
|
|||
};
|
||||
|
||||
// Create the connection string for the AdventureWorks sample database.
|
||||
const string connectionString = "Data Source=localhost;Initial Catalog=AdventureWorks;"
|
||||
+ "Integrated Security=true;";
|
||||
const string connectionString = "...";
|
||||
|
||||
// Create the command strings for querying the Contact table.
|
||||
const string contactSelectCommand = "SELECT ContactID, Title, FirstName, LastName, EmailAddress, Phone FROM Person.Contact";
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFrameworks>net6.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
|
||||
<PackageReference Include="System.Data.Odbc" Version="7.0.0" />
|
||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.6" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,42 +0,0 @@
|
|||
using System;
|
||||
using System.Configuration;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
static class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
BuildConnectionString("(local)", "Nate", "somepassword");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
// <Snippet1>
|
||||
static void BuildConnectionString(string dataSource,
|
||||
string userName, string userPassword)
|
||||
{
|
||||
// Retrieve the partial connection string named databaseConnection
|
||||
// from the application's app.config or web.config file.
|
||||
ConnectionStringSettings settings =
|
||||
ConfigurationManager.ConnectionStrings["partialConnectString"];
|
||||
|
||||
if (settings != null)
|
||||
{
|
||||
// Retrieve the partial connection string.
|
||||
var connectString = settings.ConnectionString;
|
||||
Console.WriteLine("Original: {0}", connectString);
|
||||
|
||||
// Create a new SqlConnectionStringBuilder based on the
|
||||
// partial connection string retrieved from the config file.
|
||||
SqlConnectionStringBuilder builder =
|
||||
new(connectString)
|
||||
{
|
||||
// Supply the additional values.
|
||||
DataSource = dataSource,
|
||||
UserID = userName,
|
||||
Password = userPassword
|
||||
};
|
||||
Console.WriteLine("Modified: {0}", builder.ConnectionString);
|
||||
}
|
||||
}
|
||||
// </Snippet1>
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
|
@ -12,11 +12,17 @@
|
|||
<AssemblyName>DataViewWinFormsSampleVB</AssemblyName>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<MyType>WindowsForms</MyType>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
|
||||
<OptionExplicit>On</OptionExplicit>
|
||||
<OptionCompare>Binary</OptionCompare>
|
||||
<OptionStrict>Off</OptionStrict>
|
||||
<OptionInfer>On</OptionInfer>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
<UpgradeBackupLocation>
|
||||
</UpgradeBackupLocation>
|
||||
<OldToolsVersion>3.5</OldToolsVersion>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -25,7 +31,8 @@
|
|||
<DefineTrace>true</DefineTrace>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DocumentationFile>DataViewWinFormsSampleVB.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022,42353,42354,42355</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -34,7 +41,8 @@
|
|||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DocumentationFile>DataViewWinFormsSampleVB.xml</DocumentationFile>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
|
||||
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022,42353,42354,42355</NoWarn>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
|
@ -77,6 +85,7 @@
|
|||
<Compile Include="My Project\Application.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Application.myapp</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="My Project\Resources.Designer.vb">
|
||||
<AutoGen>True</AutoGen>
|
||||
|
@ -102,6 +111,7 @@
|
|||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="My Project\Application.myapp">
|
||||
<Generator>MyApplicationCodeGenerator</Generator>
|
||||
<LastGenOutput>Application.Designer.vb</LastGenOutput>
|
||||
|
|
|
@ -24,7 +24,7 @@ Public Class Form1
|
|||
|
||||
contactDataGridView.DataSource = contactBindingSource
|
||||
|
||||
' Create a LinqDataView from a LINQ to DataSet query and bind it
|
||||
' Create a LinqDataView from a LINQ to DataSet query and bind it
|
||||
' to the Windows forms control.
|
||||
Dim contactQuery = _
|
||||
From row In dataSet.Tables("Contact").AsEnumerable() _
|
||||
|
@ -48,8 +48,7 @@ Public Class Form1
|
|||
dataSet.Locale = CultureInfo.InvariantCulture
|
||||
|
||||
' Create the connection string for the AdventureWorks sample database.
|
||||
Dim connectionString As String = "Data Source=localhost;Initial Catalog=AdventureWorks;" _
|
||||
& "Integrated Security=true;"
|
||||
Dim connectionString As String = "..."
|
||||
|
||||
' Create the command strings for querying the Contact table.
|
||||
Dim contactSelectCommand As String = "SELECT ContactID, Title, FirstName, LastName, EmailAddress, Phone FROM Person.Contact"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:2.0.50727.1378
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
|
@ -34,5 +34,11 @@ Namespace My
|
|||
Protected Overrides Sub OnCreateMainForm()
|
||||
Me.MainForm = Global.DataViewWinFormsSampleVB.Form1
|
||||
End Sub
|
||||
|
||||
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
|
||||
Protected Overrides Function OnInitialize(ByVal commandLineArgs As System.Collections.ObjectModel.ReadOnlyCollection(Of String)) As Boolean
|
||||
Me.MinimumSplashScreenDisplayTime = 0
|
||||
Return MyBase.OnInitialize(commandLineArgs)
|
||||
End Function
|
||||
End Class
|
||||
End Namespace
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:2.0.50727.1378
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
|
@ -11,6 +11,7 @@
|
|||
Option Strict On
|
||||
Option Explicit On
|
||||
|
||||
Imports System
|
||||
|
||||
Namespace My.Resources
|
||||
|
||||
|
@ -18,10 +19,10 @@ Namespace My.Resources
|
|||
'class via a tool like ResGen or Visual Studio.
|
||||
'To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
'with the /str option, or rebuild your VS project.
|
||||
'<summary>
|
||||
' A strongly-typed resource class, for looking up localized strings, etc.
|
||||
'</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0"), _
|
||||
'''<summary>
|
||||
''' A strongly-typed resource class, for looking up localized strings, etc.
|
||||
'''</summary>
|
||||
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0"), _
|
||||
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
|
||||
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
|
||||
|
@ -31,9 +32,9 @@ Namespace My.Resources
|
|||
|
||||
Private resourceCulture As Global.System.Globalization.CultureInfo
|
||||
|
||||
'<summary>
|
||||
' Returns the cached ResourceManager instance used by this class.
|
||||
'</summary>
|
||||
'''<summary>
|
||||
''' Returns the cached ResourceManager instance used by this class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
|
||||
Get
|
||||
|
@ -45,16 +46,16 @@ Namespace My.Resources
|
|||
End Get
|
||||
End Property
|
||||
|
||||
'<summary>
|
||||
' Overrides the current thread's CurrentUICulture property for all
|
||||
' resource lookups using this strongly typed resource class.
|
||||
'</summary>
|
||||
'''<summary>
|
||||
''' Overrides the current thread's CurrentUICulture property for all
|
||||
''' resource lookups using this strongly typed resource class.
|
||||
'''</summary>
|
||||
<Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Friend Property Culture() As Global.System.Globalization.CultureInfo
|
||||
Get
|
||||
Return resourceCulture
|
||||
End Get
|
||||
Set(ByVal value As Global.System.Globalization.CultureInfo)
|
||||
Set
|
||||
resourceCulture = value
|
||||
End Set
|
||||
End Property
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'------------------------------------------------------------------------------
|
||||
' <auto-generated>
|
||||
' This code was generated by a tool.
|
||||
' Runtime Version:2.0.50727.1378
|
||||
' Runtime Version:4.0.30319.42000
|
||||
'
|
||||
' Changes to this file may cause incorrect behavior and will be lost if
|
||||
' the code is regenerated.
|
||||
|
@ -13,27 +13,27 @@ Option Explicit On
|
|||
|
||||
|
||||
Namespace My
|
||||
|
||||
|
||||
<Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0"), _
|
||||
Global.System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0"), _
|
||||
Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Partial Friend NotInheritable Class MySettings
|
||||
Inherits Global.System.Configuration.ApplicationSettingsBase
|
||||
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings)
|
||||
Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings)
|
||||
|
||||
#Region "My.Settings Auto-Save Functionality"
|
||||
#If _MyType = "WindowsForms" Then
|
||||
Private Shared addedHandler As Boolean
|
||||
Private Shared addedHandler As Boolean
|
||||
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
Private Shared addedHandlerLockObject As New Object
|
||||
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)> _
|
||||
Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs)
|
||||
If My.Application.SaveMySettingsOnExit Then
|
||||
My.Settings.Save()
|
||||
End If
|
||||
End Sub
|
||||
#End If
|
||||
#End Region
|
||||
|
||||
|
@ -41,14 +41,14 @@ Namespace My
|
|||
Get
|
||||
|
||||
#If _MyType = "WindowsForms" Then
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
If Not addedHandler Then
|
||||
SyncLock addedHandlerLockObject
|
||||
If Not addedHandler Then
|
||||
AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings
|
||||
addedHandler = True
|
||||
End If
|
||||
End SyncLock
|
||||
End If
|
||||
#End If
|
||||
Return defaultInstance
|
||||
End Get
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<system.diagnostics>
|
||||
<sources>
|
||||
<!-- This section defines the logging configuration for My.Application.Log -->
|
||||
<source name="DefaultSource" switchName="DefaultSwitch">
|
||||
<listeners>
|
||||
<add name="FileLog"/>
|
||||
<!-- Uncomment the below section to write to the Application Event Log -->
|
||||
<!--<add name="EventLog"/>-->
|
||||
</listeners>
|
||||
</source>
|
||||
</sources>
|
||||
<switches>
|
||||
<add name="DefaultSwitch" value="Information"/>
|
||||
</switches>
|
||||
<sharedListeners>
|
||||
<add name="FileLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" initializeData="FileLogWriter"/>
|
||||
<!-- Uncomment the below section and replace APPLICATION_NAME with the name of your application to write to the Application Event Log -->
|
||||
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
|
||||
</sharedListeners>
|
||||
</system.diagnostics>
|
||||
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8.1"/></startup></configuration>
|
|
@ -1,44 +0,0 @@
|
|||
Option Explicit On
|
||||
Option Strict On
|
||||
|
||||
Imports System.Data
|
||||
Imports System.Data.SqlClient
|
||||
Imports System.Configuration
|
||||
|
||||
Module Module1
|
||||
|
||||
Sub Main()
|
||||
BuildConnectionString("(local)", "Nate", "somepassword")
|
||||
Console.ReadLine()
|
||||
|
||||
End Sub
|
||||
|
||||
' <Snippet1>
|
||||
Private Sub BuildConnectionString(ByVal dataSource As String, _
|
||||
ByVal userName As String, ByVal userPassword As String)
|
||||
|
||||
' Retrieve the partial connection string named databaseConnection
|
||||
' from the application's app.config or web.config file.
|
||||
Dim settings As ConnectionStringSettings = _
|
||||
ConfigurationManager.ConnectionStrings("partialConnectString")
|
||||
|
||||
If Not settings Is Nothing Then
|
||||
' Retrieve the partial connection string.
|
||||
Dim connectString As String = settings.ConnectionString
|
||||
Console.WriteLine("Original: {0}", connectString)
|
||||
|
||||
' Create a new SqlConnectionStringBuilder based on the
|
||||
' partial connection string retrieved from the config file.
|
||||
Dim builder As New SqlConnectionStringBuilder(connectString)
|
||||
|
||||
' Supply the additional values.
|
||||
builder.DataSource = dataSource
|
||||
builder.UserID = userName
|
||||
builder.Password = userPassword
|
||||
|
||||
Console.WriteLine("Modified: {0}", builder.ConnectionString)
|
||||
End If
|
||||
End Sub
|
||||
' </Snippet1>
|
||||
|
||||
End Module
|
Загрузка…
Ссылка в новой задаче